public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
@ 2008-06-18 12:34 Menon, Nishanth
  2008-06-18 15:30 ` Sascha Hauer
  0 siblings, 1 reply; 8+ messages in thread
From: Menon, Nishanth @ 2008-06-18 12:34 UTC (permalink / raw)
  To: u-boot

Add linux-like bitops definitions - this is based on 2.6.25 rc5 kernel

Signed-off-by: Nishanth Menon <x0nishan@ti.com>

---
 arch/arm/lib/Makefile    |    1
 arch/arm/lib/findbit.S   |  181 +++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-arm/bitops.h |   86 +++++++++++++++++++++-
 3 files changed, 265 insertions(+), 3 deletions(-)

Index: u-boot-v2.git/arch/arm/lib/findbit.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/arch/arm/lib/findbit.S        2008-06-17 17:01:06.000000000 -0500
@@ -0,0 +1,181 @@
+/**
+ * @file
+ * @brief common bitops
+ */
+/*
+ * Originally from Linux kernel
+ *  arch/arm/lib/findbit.S
+ *
+ *  Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 16th March 2001 - John Ripley <jripley@sonicblue.com>
+ *   Fixed so that "size" is an exclusive not an inclusive quantity.
+ *   All users of these functions expect exclusive sizes, and may
+ *   also call with zero size.
+ * Reworked by rmk.
+ */
+                .text
+
+/*
+ * Purpose  : Find a 'zero' bit
+ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
+ */
+       .globl _find_first_zero_bit_le;
+_find_first_zero_bit_le:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             ldrb    r3, [r0, r2, lsr #3]
+               eors    r3, r3, #0xff           @ invert bits
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+/*
+ * Purpose  : Find next 'zero' bit
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
+ *                                     int offset)
+ */
+       .globl _find_next_zero_bit_le;
+_find_next_zero_bit_le:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               ldrb    r3, [r0, r2, lsr #3]
+               eor     r3, r3, #0xff           @ now looking for a 1 bit
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+/*
+ * Purpose  : Find a 'one' bit
+ * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit)
+ */
+       .globl _find_first_bit_le;
+_find_first_bit_le:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             ldrb    r3, [r0, r2, lsr #3]
+               movs    r3, r3
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+/*
+ * Purpose  : Find next 'one' bit
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
+ *                                     int offset)
+ */
+       .globl _find_next_bit_le;
+_find_next_bit_le:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               ldrb    r3, [r0, r2, lsr #3]
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+#ifdef __ARMEB__
+
+       .globl _find_first_zero_bit_be;
+_find_first_zero_bit_be:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               eors    r3, r3, #0xff           @ invert bits
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+       .globl _find_next_zero_bit_be;
+_find_next_zero_bit_be:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               eor     r3, r3, #0xff           @ now looking for a 1 bit
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+       .globl _find_first_bit_be;
+_find_first_bit_be:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               movs    r3, r3
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+       .globl _find_next_bit_be;
+_find_next_bit_be:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+#endif
+
+/*
+ * One or more bits in the LSB of r3 are assumed to be set.
+ */
+.L_found:
+#if __LINUX_ARM_ARCH__ >= 5
+               rsb     r1, r3, #0
+               and     r3, r3, r1
+               clz     r3, r3
+               rsb     r3, r3, #31
+               add     r0, r2, r3
+#else
+               tst     r3, #0x0f
+               addeq   r2, r2, #4
+               movne   r3, r3, lsl #4
+               tst     r3, #0x30
+               addeq   r2, r2, #2
+               movne   r3, r3, lsl #2
+               tst     r3, #0x40
+               addeq   r2, r2, #1
+               mov     r0, r2
+#endif
+               mov     pc, lr
+
Index: u-boot-v2.git/arch/arm/lib/Makefile
===================================================================
--- u-boot-v2.git.orig/arch/arm/lib/Makefile    2008-06-17 16:52:31.000000000 -0500
+++ u-boot-v2.git/arch/arm/lib/Makefile 2008-06-17 17:01:06.000000000 -0500
@@ -8,6 +8,7 @@
 obj-y  += _udivsi3.o
 obj-y  += _umodsi3.o
 obj-y  += _lshrdi3.o
+obj-y  += findbit.o
 obj-y  += arm.o
 obj-$(CONFIG_MODULES) += module.o
 extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += u-boot.lds
Index: u-boot-v2.git/include/asm-arm/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/asm-arm/bitops.h 2008-06-17 16:52:31.000000000 -0500
+++ u-boot-v2.git/include/asm-arm/bitops.h      2008-06-17 17:01:06.000000000 -0500
@@ -75,9 +75,6 @@
        return oldval & mask;
 }

-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit(void * addr, int size, int offset);
-
 /*
  * This routine doesn't need to be atomic.
  */
@@ -86,6 +83,44 @@
     return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
 }

+
+
+
+#ifndef __ARMEB__
+/*
+ * These are the little endian definitions.
+ */
+extern int _find_first_zero_bit_le(const void *p, unsigned size);
+extern int _find_next_zero_bit_le(const void *p, int size, int offset);
+extern int _find_first_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
+#define find_first_zero_bit(p, sz)     _find_first_zero_bit_le(p, sz)
+#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_le(p, sz, off)
+#define find_first_bit(p, sz)          _find_first_bit_le(p, sz)
+#define find_next_bit(p, sz, off)      _find_next_bit_le(p, sz, off)
+
+#define WORD_BITOFF_TO_LE(x)           ((x))
+
+#else
+
+/*
+ * These are the big endian definitions.
+ */
+extern int _find_first_zero_bit_be(const void *p, unsigned size);
+extern int _find_next_zero_bit_be(const void *p, int size, int offset);
+extern int _find_first_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
+#define find_first_zero_bit(p, sz)     _find_first_zero_bit_be(p, sz)
+#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_be(p, sz, off)
+#define find_first_bit(p, sz)          _find_first_bit_be(p, sz)
+#define find_next_bit(p, sz, off)      _find_next_bit_be(p, sz, off)
+
+#define WORD_BITOFF_TO_LE(x)           ((x) ^ 0x18)
+
+#endif
+
+#if (defined(__LINUX_ARM_ARCH__) && (__LINUX_ARM_ARCH__ < 5))
+
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
@@ -112,6 +147,51 @@

 #define ffs(x) generic_ffs(x)

+#else
+
+static inline int constant_fls(int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+
+/*
+ * On ARMv5 and above those functions can be implemented around
+ * the clz instruction for much better code efficiency.
+ */
+
+#define fls(x) \
+       (__builtin_constant_p(x) ? constant_fls(x) : \
+       ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }))
+#define ffs(x) ({ unsigned long __t = (x); fls(__t &-__t); })
+#define __ffs(x) (ffs(x) - 1)
+#define ffz(x) __ffs(~(x))
+
+#endif
+
 /*
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
  2008-06-18 12:34 [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops Menon, Nishanth
@ 2008-06-18 15:30 ` Sascha Hauer
  2008-06-18 15:41   ` Menon, Nishanth
  0 siblings, 1 reply; 8+ messages in thread
From: Sascha Hauer @ 2008-06-18 15:30 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 18, 2008 at 07:34:05AM -0500, Menon, Nishanth wrote:
> Add linux-like bitops definitions - this is based on 2.6.25 rc5 kernel

I haven't looked at it, but I guess you need these for the following
patches. It would be better to first introduce generic bitops. Otherwise
we end up with i2c only working on arm.

Sascha

> 
> Signed-off-by: Nishanth Menon <x0nishan@ti.com>
> 
> ---
>  arch/arm/lib/Makefile    |    1
>  arch/arm/lib/findbit.S   |  181 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/asm-arm/bitops.h |   86 +++++++++++++++++++++-
>  3 files changed, 265 insertions(+), 3 deletions(-)
> 
> Index: u-boot-v2.git/arch/arm/lib/findbit.S
> ===================================================================
> --- /dev/null   1970-01-01 00:00:00.000000000 +0000
> +++ u-boot-v2.git/arch/arm/lib/findbit.S        2008-06-17 17:01:06.000000000 -0500
> @@ -0,0 +1,181 @@
> +/**
> + * @file
> + * @brief common bitops
> + */
> +/*
> + * Originally from Linux kernel
> + *  arch/arm/lib/findbit.S
> + *
> + *  Copyright (C) 1995-2000 Russell King
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * 16th March 2001 - John Ripley <jripley@sonicblue.com>
> + *   Fixed so that "size" is an exclusive not an inclusive quantity.
> + *   All users of these functions expect exclusive sizes, and may
> + *   also call with zero size.
> + * Reworked by rmk.
> + */
> +                .text
> +
> +/*
> + * Purpose  : Find a 'zero' bit
> + * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
> + */
> +       .globl _find_first_zero_bit_le;
> +_find_first_zero_bit_le:
> +               teq     r1, #0
> +               beq     3f
> +               mov     r2, #0
> +1:             ldrb    r3, [r0, r2, lsr #3]
> +               eors    r3, r3, #0xff           @ invert bits
> +               bne     .L_found                @ any now set - found zero bit
> +               add     r2, r2, #8              @ next bit pointer
> +2:             cmp     r2, r1                  @ any more?
> +               blo     1b
> +3:             mov     r0, r1                  @ no free bits
> +               mov     pc, lr
> +
> +/*
> + * Purpose  : Find next 'zero' bit
> + * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
> + *                                     int offset)
> + */
> +       .globl _find_next_zero_bit_le;
> +_find_next_zero_bit_le:
> +               teq     r1, #0
> +               beq     3b
> +               ands    ip, r2, #7
> +               beq     1b                      @ If new byte, goto old routine
> +               ldrb    r3, [r0, r2, lsr #3]
> +               eor     r3, r3, #0xff           @ now looking for a 1 bit
> +               movs    r3, r3, lsr ip          @ shift off unused bits
> +               bne     .L_found
> +               orr     r2, r2, #7              @ if zero, then no bits here
> +               add     r2, r2, #1              @ align bit pointer
> +               b       2b                      @ loop for next bit
> +
> +/*
> + * Purpose  : Find a 'one' bit
> + * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit)
> + */
> +       .globl _find_first_bit_le;
> +_find_first_bit_le:
> +               teq     r1, #0
> +               beq     3f
> +               mov     r2, #0
> +1:             ldrb    r3, [r0, r2, lsr #3]
> +               movs    r3, r3
> +               bne     .L_found                @ any now set - found zero bit
> +               add     r2, r2, #8              @ next bit pointer
> +2:             cmp     r2, r1                  @ any more?
> +               blo     1b
> +3:             mov     r0, r1                  @ no free bits
> +               mov     pc, lr
> +
> +/*
> + * Purpose  : Find next 'one' bit
> + * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
> + *                                     int offset)
> + */
> +       .globl _find_next_bit_le;
> +_find_next_bit_le:
> +               teq     r1, #0
> +               beq     3b
> +               ands    ip, r2, #7
> +               beq     1b                      @ If new byte, goto old routine
> +               ldrb    r3, [r0, r2, lsr #3]
> +               movs    r3, r3, lsr ip          @ shift off unused bits
> +               bne     .L_found
> +               orr     r2, r2, #7              @ if zero, then no bits here
> +               add     r2, r2, #1              @ align bit pointer
> +               b       2b                      @ loop for next bit
> +
> +#ifdef __ARMEB__
> +
> +       .globl _find_first_zero_bit_be;
> +_find_first_zero_bit_be:
> +               teq     r1, #0
> +               beq     3f
> +               mov     r2, #0
> +1:             eor     r3, r2, #0x18           @ big endian byte ordering
> +               ldrb    r3, [r0, r3, lsr #3]
> +               eors    r3, r3, #0xff           @ invert bits
> +               bne     .L_found                @ any now set - found zero bit
> +               add     r2, r2, #8              @ next bit pointer
> +2:             cmp     r2, r1                  @ any more?
> +               blo     1b
> +3:             mov     r0, r1                  @ no free bits
> +               mov     pc, lr
> +
> +       .globl _find_next_zero_bit_be;
> +_find_next_zero_bit_be:
> +               teq     r1, #0
> +               beq     3b
> +               ands    ip, r2, #7
> +               beq     1b                      @ If new byte, goto old routine
> +               eor     r3, r2, #0x18           @ big endian byte ordering
> +               ldrb    r3, [r0, r3, lsr #3]
> +               eor     r3, r3, #0xff           @ now looking for a 1 bit
> +               movs    r3, r3, lsr ip          @ shift off unused bits
> +               bne     .L_found
> +               orr     r2, r2, #7              @ if zero, then no bits here
> +               add     r2, r2, #1              @ align bit pointer
> +               b       2b                      @ loop for next bit
> +
> +       .globl _find_first_bit_be;
> +_find_first_bit_be:
> +               teq     r1, #0
> +               beq     3f
> +               mov     r2, #0
> +1:             eor     r3, r2, #0x18           @ big endian byte ordering
> +               ldrb    r3, [r0, r3, lsr #3]
> +               movs    r3, r3
> +               bne     .L_found                @ any now set - found zero bit
> +               add     r2, r2, #8              @ next bit pointer
> +2:             cmp     r2, r1                  @ any more?
> +               blo     1b
> +3:             mov     r0, r1                  @ no free bits
> +               mov     pc, lr
> +
> +       .globl _find_next_bit_be;
> +_find_next_bit_be:
> +               teq     r1, #0
> +               beq     3b
> +               ands    ip, r2, #7
> +               beq     1b                      @ If new byte, goto old routine
> +               eor     r3, r2, #0x18           @ big endian byte ordering
> +               ldrb    r3, [r0, r3, lsr #3]
> +               movs    r3, r3, lsr ip          @ shift off unused bits
> +               bne     .L_found
> +               orr     r2, r2, #7              @ if zero, then no bits here
> +               add     r2, r2, #1              @ align bit pointer
> +               b       2b                      @ loop for next bit
> +
> +#endif
> +
> +/*
> + * One or more bits in the LSB of r3 are assumed to be set.
> + */
> +.L_found:
> +#if __LINUX_ARM_ARCH__ >= 5
> +               rsb     r1, r3, #0
> +               and     r3, r3, r1
> +               clz     r3, r3
> +               rsb     r3, r3, #31
> +               add     r0, r2, r3
> +#else
> +               tst     r3, #0x0f
> +               addeq   r2, r2, #4
> +               movne   r3, r3, lsl #4
> +               tst     r3, #0x30
> +               addeq   r2, r2, #2
> +               movne   r3, r3, lsl #2
> +               tst     r3, #0x40
> +               addeq   r2, r2, #1
> +               mov     r0, r2
> +#endif
> +               mov     pc, lr
> +
> Index: u-boot-v2.git/arch/arm/lib/Makefile
> ===================================================================
> --- u-boot-v2.git.orig/arch/arm/lib/Makefile    2008-06-17 16:52:31.000000000 -0500
> +++ u-boot-v2.git/arch/arm/lib/Makefile 2008-06-17 17:01:06.000000000 -0500
> @@ -8,6 +8,7 @@
>  obj-y  += _udivsi3.o
>  obj-y  += _umodsi3.o
>  obj-y  += _lshrdi3.o
> +obj-y  += findbit.o
>  obj-y  += arm.o
>  obj-$(CONFIG_MODULES) += module.o
>  extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += u-boot.lds
> Index: u-boot-v2.git/include/asm-arm/bitops.h
> ===================================================================
> --- u-boot-v2.git.orig/include/asm-arm/bitops.h 2008-06-17 16:52:31.000000000 -0500
> +++ u-boot-v2.git/include/asm-arm/bitops.h      2008-06-17 17:01:06.000000000 -0500
> @@ -75,9 +75,6 @@
>         return oldval & mask;
>  }
> 
> -extern int find_first_zero_bit(void * addr, unsigned size);
> -extern int find_next_zero_bit(void * addr, int size, int offset);
> -
>  /*
>   * This routine doesn't need to be atomic.
>   */
> @@ -86,6 +83,44 @@
>      return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
>  }
> 
> +
> +
> +
> +#ifndef __ARMEB__
> +/*
> + * These are the little endian definitions.
> + */
> +extern int _find_first_zero_bit_le(const void *p, unsigned size);
> +extern int _find_next_zero_bit_le(const void *p, int size, int offset);
> +extern int _find_first_bit_le(const unsigned long *p, unsigned size);
> +extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
> +#define find_first_zero_bit(p, sz)     _find_first_zero_bit_le(p, sz)
> +#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_le(p, sz, off)
> +#define find_first_bit(p, sz)          _find_first_bit_le(p, sz)
> +#define find_next_bit(p, sz, off)      _find_next_bit_le(p, sz, off)
> +
> +#define WORD_BITOFF_TO_LE(x)           ((x))
> +
> +#else
> +
> +/*
> + * These are the big endian definitions.
> + */
> +extern int _find_first_zero_bit_be(const void *p, unsigned size);
> +extern int _find_next_zero_bit_be(const void *p, int size, int offset);
> +extern int _find_first_bit_be(const unsigned long *p, unsigned size);
> +extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
> +#define find_first_zero_bit(p, sz)     _find_first_zero_bit_be(p, sz)
> +#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_be(p, sz, off)
> +#define find_first_bit(p, sz)          _find_first_bit_be(p, sz)
> +#define find_next_bit(p, sz, off)      _find_next_bit_be(p, sz, off)
> +
> +#define WORD_BITOFF_TO_LE(x)           ((x) ^ 0x18)
> +
> +#endif
> +
> +#if (defined(__LINUX_ARM_ARCH__) && (__LINUX_ARM_ARCH__ < 5))
> +
>  /*
>   * ffz = Find First Zero in word. Undefined if no zero exists,
>   * so code should check against ~0UL first..
> @@ -112,6 +147,51 @@
> 
>  #define ffs(x) generic_ffs(x)
> 
> +#else
> +
> +static inline int constant_fls(int x)
> +{
> +       int r = 32;
> +
> +       if (!x)
> +               return 0;
> +       if (!(x & 0xffff0000u)) {
> +               x <<= 16;
> +               r -= 16;
> +       }
> +       if (!(x & 0xff000000u)) {
> +               x <<= 8;
> +               r -= 8;
> +       }
> +       if (!(x & 0xf0000000u)) {
> +               x <<= 4;
> +               r -= 4;
> +       }
> +       if (!(x & 0xc0000000u)) {
> +               x <<= 2;
> +               r -= 2;
> +       }
> +       if (!(x & 0x80000000u)) {
> +               x <<= 1;
> +               r -= 1;
> +       }
> +       return r;
> +}
> +
> +/*
> + * On ARMv5 and above those functions can be implemented around
> + * the clz instruction for much better code efficiency.
> + */
> +
> +#define fls(x) \
> +       (__builtin_constant_p(x) ? constant_fls(x) : \
> +       ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }))
> +#define ffs(x) ({ unsigned long __t = (x); fls(__t &-__t); })
> +#define __ffs(x) (ffs(x) - 1)
> +#define ffz(x) __ffs(~(x))
> +
> +#endif
> +
>  /*
>   * hweightN: returns the hamming weight (i.e. the number
>   * of bits set) of a N-bit word
> 

-- 
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
  2008-06-18 15:30 ` Sascha Hauer
@ 2008-06-18 15:41   ` Menon, Nishanth
  2008-06-18 15:50     ` Sascha Hauer
  0 siblings, 1 reply; 8+ messages in thread
From: Menon, Nishanth @ 2008-06-18 15:41 UTC (permalink / raw)
  To: u-boot

Sascha,
> -----Original Message-----
> From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> Sent: Wednesday, June 18, 2008 10:31 AM
> To: Menon, Nishanth
> Cc: Kamat, Nishant; u-boot-users at lists.sourceforge.net; Laurent Desnogues; philip.balister at gmail.com;
> dirk.behme at googlemail.com
> Subject: Re: [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
>
> On Wed, Jun 18, 2008 at 07:34:05AM -0500, Menon, Nishanth wrote:
> > Add linux-like bitops definitions - this is based on 2.6.25 rc5 kernel
>
> I haven't looked at it, but I guess you need these for the following
> patches. It would be better to first introduce generic bitops. Otherwise
> we end up with i2c only working on arm.
Would you have a proposal for it? I am not familiar with ppc and other archs :( I can help on ARM side of things.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
  2008-06-18 15:41   ` Menon, Nishanth
@ 2008-06-18 15:50     ` Sascha Hauer
  2008-06-19  6:12       ` [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops Menon, Nishanth
                         ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Sascha Hauer @ 2008-06-18 15:50 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 18, 2008 at 10:41:44AM -0500, Menon, Nishanth wrote:
> Sascha,
> > -----Original Message-----
> > From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> > Sent: Wednesday, June 18, 2008 10:31 AM
> > To: Menon, Nishanth
> > Cc: Kamat, Nishant; u-boot-users at lists.sourceforge.net; Laurent Desnogues; philip.balister at gmail.com;
> > dirk.behme at googlemail.com
> > Subject: Re: [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
> >
> > On Wed, Jun 18, 2008 at 07:34:05AM -0500, Menon, Nishanth wrote:
> > > Add linux-like bitops definitions - this is based on 2.6.25 rc5 kernel
> >
> > I haven't looked at it, but I guess you need these for the following
> > patches. It would be better to first introduce generic bitops. Otherwise
> > we end up with i2c only working on arm.
> Would you have a proposal for it? I am not familiar with ppc and other archs :( I can help on ARM side of things.

In the kernel are generic bitops, #ifdefed with CONFIG_GENERIC_XXX

Regards,
 Sascha

-- 
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops
  2008-06-18 15:50     ` Sascha Hauer
@ 2008-06-19  6:12       ` Menon, Nishanth
  2008-06-19 12:56         ` Jon Loeliger
  2008-06-19  6:13       ` [U-Boot-Users] [Patch 2/3] U-Boot-V2: Bitops cleanup: cleanup ARM bitops Menon, Nishanth
  2008-06-19  6:13       ` [U-Boot-Users] [Patch 3/3] U-Boot-V2: Bitops cleanup: cleanup rest of generic_xxx functions Menon, Nishanth
  2 siblings, 1 reply; 8+ messages in thread
From: Menon, Nishanth @ 2008-06-19  6:12 UTC (permalink / raw)
  To: u-boot

Sascha,
The following 3 patches are for cleaning up the bitops
> -----Original Message-----
> From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> Sent: Wednesday, June 18, 2008 10:51 AM
> To: Menon, Nishanth
> Cc: Kamat, Nishant; u-boot-users at lists.sourceforge.net; Laurent Desnogues; philip.balister at gmail.com;
> dirk.behme at googlemail.com
> Subject: Re: [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
>
>
> In the kernel are generic bitops, #ifdefed with CONFIG_GENERIC_XXX

This introduces selected generic bitop files from kernel. We don't need minix, ext2, sched or lock based bitops. Those have been dropped.

Signed-off-by: Nishanth Menon <x0nishan@ti.com>

---
 include/asm-generic/bitops/__ffs.h   |   43 ++++++++++++++++
 include/asm-generic/bitops/__fls.h   |   43 ++++++++++++++++
 include/asm-generic/bitops/ffs.h     |   41 +++++++++++++++
 include/asm-generic/bitops/ffz.h     |   12 ++++
 include/asm-generic/bitops/find.h    |   15 +++++
 include/asm-generic/bitops/fls.h     |   41 +++++++++++++++
 include/asm-generic/bitops/fls64.h   |   36 +++++++++++++
 include/asm-generic/bitops/hweight.h |   35 +++++++++++++
 include/asm-generic/bitops/ops.h     |   91 +++++++++++++++++++++++++++++++++++
 9 files changed, 357 insertions(+)

Index: u-boot-v2.git/include/asm-generic/bitops/__ffs.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/__ffs.h    2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,43 @@
+#ifndef _ASM_GENERIC_BITOPS___FFS_H_
+#define _ASM_GENERIC_BITOPS___FFS_H_
+
+#include <asm/types.h>
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+       int num = 0;
+
+#if BITS_PER_LONG == 64
+       if ((word & 0xffffffff) == 0) {
+               num += 32;
+               word >>= 32;
+       }
+#endif
+       if ((word & 0xffff) == 0) {
+               num += 16;
+               word >>= 16;
+       }
+       if ((word & 0xff) == 0) {
+               num += 8;
+               word >>= 8;
+       }
+       if ((word & 0xf) == 0) {
+               num += 4;
+               word >>= 4;
+       }
+       if ((word & 0x3) == 0) {
+               num += 2;
+               word >>= 2;
+       }
+       if ((word & 0x1) == 0)
+               num += 1;
+       return num;
+}
+
+#endif /* _ASM_GENERIC_BITOPS___FFS_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/__fls.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/__fls.h    2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,43 @@
+#ifndef _ASM_GENERIC_BITOPS___FLS_H_
+#define _ASM_GENERIC_BITOPS___FLS_H_
+
+#include <asm/types.h>
+
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       int num = BITS_PER_LONG - 1;
+
+#if BITS_PER_LONG == 64
+       if (!(word & (~0ul << 32))) {
+               num -= 32;
+               word <<= 32;
+       }
+#endif
+       if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
+               num -= 16;
+               word <<= 16;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
+               num -= 8;
+               word <<= 8;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
+               num -= 4;
+               word <<= 4;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
+               num -= 2;
+               word <<= 2;
+       }
+       if (!(word & (~0ul << (BITS_PER_LONG-1))))
+               num -= 1;
+       return num;
+}
+
+#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/ffs.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/ffs.h      2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,41 @@
+#ifndef _ASM_GENERIC_BITOPS_FFS_H_
+#define _ASM_GENERIC_BITOPS_FFS_H_
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline int ffs(int x)
+{
+       int r = 1;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff)) {
+               x >>= 16;
+               r += 16;
+       }
+       if (!(x & 0xff)) {
+               x >>= 8;
+               r += 8;
+       }
+       if (!(x & 0xf)) {
+               x >>= 4;
+               r += 4;
+       }
+       if (!(x & 3)) {
+               x >>= 2;
+               r += 2;
+       }
+       if (!(x & 1)) {
+               x >>= 1;
+               r += 1;
+       }
+       return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/ffz.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/ffz.h      2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,12 @@
+#ifndef _ASM_GENERIC_BITOPS_FFZ_H_
+#define _ASM_GENERIC_BITOPS_FFZ_H_
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+#define ffz(x)  __ffs(~(x))
+
+#endif /* _ASM_GENERIC_BITOPS_FFZ_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/find.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/find.h     2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,15 @@
+#ifndef _ASM_GENERIC_BITOPS_FIND_H_
+#define _ASM_GENERIC_BITOPS_FIND_H_
+
+#ifndef CONFIG_GENERIC_FIND_NEXT_BIT
+extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
+               size, unsigned long offset);
+
+extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
+               long size, unsigned long offset);
+#endif
+
+#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+
+#endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/fls.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/fls.h      2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,41 @@
+#ifndef _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS_FLS_H_
+
+/**
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static inline int fls(int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/fls64.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/fls64.h    2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
+#define _ASM_GENERIC_BITOPS_FLS64_H_
+
+#include <asm/types.h>
+
+/**
+ * fls64 - find last set bit in a 64-bit word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
+ */
+#if BITS_PER_LONG == 32
+static inline int fls64(__u64 x)
+{
+       __u32 h = x >> 32;
+       if (h)
+               return fls(h) + 32;
+       return fls(x);
+}
+#elif BITS_PER_LONG == 64
+static inline int fls64(__u64 x)
+{
+       if (x == 0)
+               return 0;
+       return __fls(x) + 1;
+}
+#else
+#error BITS_PER_LONG not 32 or 64
+#endif
+
+#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/hweight.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/hweight.h  2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,35 @@
+#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_
+#define _ASM_GENERIC_BITOPS_HWEIGHT_H_
+
+#include <asm/types.h>
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+static inline unsigned int hweight32(unsigned int w)
+{
+       unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+       res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+       res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+       res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+       return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+static inline unsigned int hweight16(unsigned int w)
+{
+       unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
+       res = (res & 0x3333) + ((res >> 2) & 0x3333);
+       res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
+       return (res & 0x00FF) + ((res >> 8) & 0x00FF);
+}
+
+static inline unsigned int hweight8(unsigned int w)
+{
+       unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
+       res = (res & 0x33) + ((res >> 2) & 0x33);
+       return (res & 0x0F) + ((res >> 4) & 0x0F);
+}
+
+#endif                         /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
Index: u-boot-v2.git/include/asm-generic/bitops/ops.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/asm-generic/bitops/ops.h      2008-06-19 01:06:03.000000000 -0500
@@ -0,0 +1,91 @@
+#ifndef _ASM_GENERIC_BITOPS_OPS_H_
+#define _ASM_GENERIC_BITOPS_OPS_H_
+
+#include <asm/types.h>
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+       *p  |= mask;
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+       *p &= ~mask;
+}
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to change
+ * @addr: the address to start counting from
+ */
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+       *p ^= mask;
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old = *p;
+
+       *p = old | mask;
+       return (old & mask) != 0;
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old = *p;
+
+       *p = old & ~mask;
+       return (old & mask) != 0;
+}
+
+static inline int __test_and_change_bit(int nr,
+                                           volatile unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old = *p;
+
+       *p = old ^ mask;
+       return (old & mask) != 0;
+}
+
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+       return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+#endif /* _ASM_GENERIC_BITOPS_OPS_H_ */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 2/3] U-Boot-V2: Bitops cleanup: cleanup ARM bitops
  2008-06-18 15:50     ` Sascha Hauer
  2008-06-19  6:12       ` [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops Menon, Nishanth
@ 2008-06-19  6:13       ` Menon, Nishanth
  2008-06-19  6:13       ` [U-Boot-Users] [Patch 3/3] U-Boot-V2: Bitops cleanup: cleanup rest of generic_xxx functions Menon, Nishanth
  2 siblings, 0 replies; 8+ messages in thread
From: Menon, Nishanth @ 2008-06-19  6:13 UTC (permalink / raw)
  To: u-boot

Cleanup of ARM bitops functions. Introduce the findbits.S which allows for optimized algo.

Signed-off-by: Nishanth Menon <x0nishan@ti.com>

---
 arch/arm/lib/Makefile    |    1
 arch/arm/lib/findbit.S   |  181 +++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-arm/bitops.h |  133 +++++++++++++++++++++++-----------
 3 files changed, 273 insertions(+), 42 deletions(-)

Index: u-boot-v2.git/arch/arm/lib/Makefile
===================================================================
--- u-boot-v2.git.orig/arch/arm/lib/Makefile    2008-06-19 00:52:51.000000000 -0500
+++ u-boot-v2.git/arch/arm/lib/Makefile 2008-06-19 00:54:17.000000000 -0500
@@ -8,6 +8,7 @@
 obj-y  += _udivsi3.o
 obj-y  += _umodsi3.o
 obj-y  += _lshrdi3.o
+obj-y  += findbit.o
 obj-y  += arm.o
 obj-$(CONFIG_MODULES) += module.o
 extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += u-boot.lds
Index: u-boot-v2.git/arch/arm/lib/findbit.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/arch/arm/lib/findbit.S        2008-06-19 00:54:17.000000000 -0500
@@ -0,0 +1,181 @@
+/**
+ * @file
+ * @brief common bitops
+ */
+/*
+ * Originally from Linux kernel
+ *  arch/arm/lib/findbit.S
+ *
+ *  Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 16th March 2001 - John Ripley <jripley@sonicblue.com>
+ *   Fixed so that "size" is an exclusive not an inclusive quantity.
+ *   All users of these functions expect exclusive sizes, and may
+ *   also call with zero size.
+ * Reworked by rmk.
+ */
+                .text
+
+/*
+ * Purpose  : Find a 'zero' bit
+ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
+ */
+       .globl _find_first_zero_bit_le;
+_find_first_zero_bit_le:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             ldrb    r3, [r0, r2, lsr #3]
+               eors    r3, r3, #0xff           @ invert bits
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+/*
+ * Purpose  : Find next 'zero' bit
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
+ *                                     int offset)
+ */
+       .globl _find_next_zero_bit_le;
+_find_next_zero_bit_le:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               ldrb    r3, [r0, r2, lsr #3]
+               eor     r3, r3, #0xff           @ now looking for a 1 bit
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+/*
+ * Purpose  : Find a 'one' bit
+ * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit)
+ */
+       .globl _find_first_bit_le;
+_find_first_bit_le:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             ldrb    r3, [r0, r2, lsr #3]
+               movs    r3, r3
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+/*
+ * Purpose  : Find next 'one' bit
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
+ *                                     int offset)
+ */
+       .globl _find_next_bit_le;
+_find_next_bit_le:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               ldrb    r3, [r0, r2, lsr #3]
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+#ifdef __ARMEB__
+
+       .globl _find_first_zero_bit_be;
+_find_first_zero_bit_be:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               eors    r3, r3, #0xff           @ invert bits
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+       .globl _find_next_zero_bit_be;
+_find_next_zero_bit_be:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               eor     r3, r3, #0xff           @ now looking for a 1 bit
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+       .globl _find_first_bit_be;
+_find_first_bit_be:
+               teq     r1, #0
+               beq     3f
+               mov     r2, #0
+1:             eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               movs    r3, r3
+               bne     .L_found                @ any now set - found zero bit
+               add     r2, r2, #8              @ next bit pointer
+2:             cmp     r2, r1                  @ any more?
+               blo     1b
+3:             mov     r0, r1                  @ no free bits
+               mov     pc, lr
+
+       .globl _find_next_bit_be;
+_find_next_bit_be:
+               teq     r1, #0
+               beq     3b
+               ands    ip, r2, #7
+               beq     1b                      @ If new byte, goto old routine
+               eor     r3, r2, #0x18           @ big endian byte ordering
+               ldrb    r3, [r0, r3, lsr #3]
+               movs    r3, r3, lsr ip          @ shift off unused bits
+               bne     .L_found
+               orr     r2, r2, #7              @ if zero, then no bits here
+               add     r2, r2, #1              @ align bit pointer
+               b       2b                      @ loop for next bit
+
+#endif
+
+/*
+ * One or more bits in the LSB of r3 are assumed to be set.
+ */
+.L_found:
+#if __LINUX_ARM_ARCH__ >= 5
+               rsb     r1, r3, #0
+               and     r3, r3, r1
+               clz     r3, r3
+               rsb     r3, r3, #31
+               add     r0, r2, r3
+#else
+               tst     r3, #0x0f
+               addeq   r2, r2, #4
+               movne   r3, r3, lsl #4
+               tst     r3, #0x30
+               addeq   r2, r2, #2
+               movne   r3, r3, lsl #2
+               tst     r3, #0x40
+               addeq   r2, r2, #1
+               mov     r0, r2
+#endif
+               mov     pc, lr
+
Index: u-boot-v2.git/include/asm-arm/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/asm-arm/bitops.h 2008-06-19 00:52:51.000000000 -0500
+++ u-boot-v2.git/include/asm-arm/bitops.h      2008-06-19 00:54:30.000000000 -0500
@@ -15,32 +15,28 @@
 #ifndef __ASM_ARM_BITOPS_H
 #define __ASM_ARM_BITOPS_H

+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
 /*
- * Function prototypes to keep gcc -Wall happy.
+ * Functions equivalent of ops.h
  */
-extern void set_bit(int nr, volatile void * addr);
-
 static inline void __set_bit(int nr, volatile void *addr)
 {
        ((unsigned char *) addr)[nr >> 3] |= (1U << (nr & 7));
 }

-extern void clear_bit(int nr, volatile void * addr);
-
 static inline void __clear_bit(int nr, volatile void *addr)
 {
        ((unsigned char *) addr)[nr >> 3] &= ~(1U << (nr & 7));
 }

-extern void change_bit(int nr, volatile void * addr);
-
 static inline void __change_bit(int nr, volatile void *addr)
 {
        ((unsigned char *) addr)[nr >> 3] ^= (1U << (nr & 7));
 }

-extern int test_and_set_bit(int nr, volatile void * addr);
-
 static inline int __test_and_set_bit(int nr, volatile void *addr)
 {
        unsigned int mask = 1 << (nr & 7);
@@ -51,8 +47,6 @@
        return oldval & mask;
 }

-extern int test_and_clear_bit(int nr, volatile void * addr);
-
 static inline int __test_and_clear_bit(int nr, volatile void *addr)
 {
        unsigned int mask = 1 << (nr & 7);
@@ -63,8 +57,6 @@
        return oldval & mask;
 }

-extern int test_and_change_bit(int nr, volatile void * addr);
-
 static inline int __test_and_change_bit(int nr, volatile void *addr)
 {
        unsigned int mask = 1 << (nr & 7);
@@ -75,9 +67,6 @@
        return oldval & mask;
 }

-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit(void * addr, int size, int offset);
-
 /*
  * This routine doesn't need to be atomic.
  */
@@ -86,6 +75,48 @@
     return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
 }

+#define set_bit(x, y)                  __set_bit(x, y)
+#define clear_bit(x, y)                        __clear_bit(x, y)
+#define change_bit(x, y)               __change_bit(x, y)
+#define test_and_set_bit(x, y)         __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y)       __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y)      __test_and_change_bit(x, y)
+
+#ifndef __ARMEB__
+/*
+ * These are the little endian definitions.
+ */
+extern int _find_first_zero_bit_le(const void *p, unsigned size);
+extern int _find_next_zero_bit_le(const void *p, int size, int offset);
+extern int _find_first_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
+#define find_first_zero_bit(p, sz)     _find_first_zero_bit_le(p, sz)
+#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_le(p, sz, off)
+#define find_first_bit(p, sz)          _find_first_bit_le(p, sz)
+#define find_next_bit(p, sz, off)      _find_next_bit_le(p, sz, off)
+
+#define WORD_BITOFF_TO_LE(x)           ((x))
+
+#else          /* ! __ARMEB__ */
+
+/*
+ * These are the big endian definitions.
+ */
+extern int _find_first_zero_bit_be(const void *p, unsigned size);
+extern int _find_next_zero_bit_be(const void *p, int size, int offset);
+extern int _find_first_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
+#define find_first_zero_bit(p, sz)     _find_first_zero_bit_be(p, sz)
+#define find_next_zero_bit(p, sz, off) _find_next_zero_bit_be(p, sz, off)
+#define find_first_bit(p, sz)          _find_first_bit_be(p, sz)
+#define find_next_bit(p, sz, off)      _find_next_bit_be(p, sz, off)
+
+#define WORD_BITOFF_TO_LE(x)           ((x) ^ 0x18)
+
+#endif         /* __ARMEB__ */
+
+#if defined(__LINUX_ARM_ARCH__) && (__LINUX_ARM_ARCH__ < 5)
+
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
@@ -103,35 +134,53 @@
        if (word & 0x40000000) { k -= 1; }
        return k;
 }
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#else          /* ! __ARM__USE_GENERIC_FF */
+
+static inline int constant_fls(int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}

 /*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
+ * On ARMv5 and above those functions can be implemented around
+ * the clz instruction for much better code efficiency.
  */
+#define fls(x) \
+       (__builtin_constant_p(x) ? constant_fls(x) : \
+       ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }))
+#define ffs(x) ({ unsigned long __t = (x); fls(__t &-__t); })
+#define __ffs(x) (ffs(x) - 1)
+#define ffz(x) __ffs(~(x))
+#endif         /* __ARM__USE_GENERIC_FF */
+#include <asm-generic/bitops/fls64.h>

-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-#define ext2_set_bit                   test_and_set_bit
-#define ext2_clear_bit                 test_and_clear_bit
-#define ext2_test_bit                  test_bit
-#define ext2_find_first_zero_bit       find_first_zero_bit
-#define ext2_find_next_zero_bit                find_next_zero_bit
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr)        test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr)         set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr)      test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr)                test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size)   find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/hweight.h>

 #endif /* _ARM_BITOPS_H */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 3/3] U-Boot-V2: Bitops cleanup: cleanup rest of generic_xxx functions
  2008-06-18 15:50     ` Sascha Hauer
  2008-06-19  6:12       ` [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops Menon, Nishanth
  2008-06-19  6:13       ` [U-Boot-Users] [Patch 2/3] U-Boot-V2: Bitops cleanup: cleanup ARM bitops Menon, Nishanth
@ 2008-06-19  6:13       ` Menon, Nishanth
  2 siblings, 0 replies; 8+ messages in thread
From: Menon, Nishanth @ 2008-06-19  6:13 UTC (permalink / raw)
  To: u-boot

Use the asm-generic/bitops/xyz.h instead of using generic_xyz functions.

Signed-off-by: Nishanth Menon <x0nishan@ti.com>

---
 include/asm-blackfin/bitops.h |   18 +---------
 include/asm-m68k/bitops.h     |   18 +---------
 include/asm-ppc/bitops.h      |    9 -----
 include/linux/bitops.h        |   71 ++++--------------------------------------
 4 files changed, 12 insertions(+), 104 deletions(-)

Index: u-boot-v2.git/include/asm-blackfin/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/asm-blackfin/bitops.h    2008-06-19 00:50:37.000000000 -0500
+++ u-boot-v2.git/include/asm-blackfin/bitops.h 2008-06-19 00:51:52.000000000 -0500
@@ -268,22 +268,8 @@
        return result + ffz(tmp);
 }

-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x)         generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x)   generic_hweight32(x)
-#define hweight16(x)   generic_hweight16(x)
-#define hweight8(x)    generic_hweight8(x)
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>

 static __inline__ int ext2_set_bit(int nr, volatile void *addr)
 {
Index: u-boot-v2.git/include/asm-m68k/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/asm-m68k/bitops.h        2008-06-19 00:50:13.000000000 -0500
+++ u-boot-v2.git/include/asm-m68k/bitops.h     2008-06-19 00:51:52.000000000 -0500
@@ -122,22 +122,8 @@
        return k;
 }

-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>

 #define ext2_set_bit                   test_and_set_bit
 #define ext2_clear_bit                 test_and_clear_bit
Index: u-boot-v2.git/include/linux/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/linux/bitops.h   2008-06-19 00:50:13.000000000 -0500
+++ u-boot-v2.git/include/linux/bitops.h        2008-06-19 00:52:34.000000000 -0500
@@ -1,70 +1,13 @@
 #ifndef _LINUX_BITOPS_H
 #define _LINUX_BITOPS_H

-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-static inline int generic_ffs(int x)
-{
-       int r = 1;
-
-       if (!x)
-               return 0;
-       if (!(x & 0xffff)) {
-               x >>= 16;
-               r += 16;
-       }
-       if (!(x & 0xff)) {
-               x >>= 8;
-               r += 8;
-       }
-       if (!(x & 0xf)) {
-               x >>= 4;
-               r += 4;
-       }
-       if (!(x & 3)) {
-               x >>= 2;
-               r += 2;
-       }
-       if (!(x & 1)) {
-               x >>= 1;
-               r += 1;
-       }
-       return r;
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-static inline unsigned int generic_hweight32(unsigned int w)
-{
-       unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
-       res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
-       res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
-       res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
-       return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
-static inline unsigned int generic_hweight16(unsigned int w)
-{
-       unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
-       res = (res & 0x3333) + ((res >> 2) & 0x3333);
-       res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
-       return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-static inline unsigned int generic_hweight8(unsigned int w)
-{
-       unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
-       res = (res & 0x33) + ((res >> 2) & 0x33);
-       return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
+#ifdef __U_BOOT__
+#define BIT(nr)                        (1UL << (nr))
+#define BIT_MASK(nr)           (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr)           ((nr) / BITS_PER_LONG)
+#define BITS_PER_BYTE          8
+#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#endif

 #include <asm/bitops.h>

Index: u-boot-v2.git/include/asm-ppc/bitops.h
===================================================================
--- u-boot-v2.git.orig/include/asm-ppc/bitops.h 2008-06-19 00:50:37.000000000 -0500
+++ u-boot-v2.git/include/asm-ppc/bitops.h      2008-06-19 00:51:52.000000000 -0500
@@ -178,14 +178,7 @@
        return __ilog2(x & -x) + 1;
 }

-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>

 #endif /* __U_BOOT__ */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops
  2008-06-19  6:12       ` [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops Menon, Nishanth
@ 2008-06-19 12:56         ` Jon Loeliger
  0 siblings, 0 replies; 8+ messages in thread
From: Jon Loeliger @ 2008-06-19 12:56 UTC (permalink / raw)
  To: u-boot

Menon, Nishanth wrote:
> Sascha,
> The following 3 patches are for cleaning up the bitops
>> -----Original Message-----
>> From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
>> Sent: Wednesday, June 18, 2008 10:51 AM
>> To: Menon, Nishanth
>> Cc: Kamat, Nishant; u-boot-users at lists.sourceforge.net; Laurent Desnogues; philip.balister at gmail.com;
>> dirk.behme at googlemail.com
>> Subject: Re: [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops
>>
>>
>> In the kernel are generic bitops, #ifdefed with CONFIG_GENERIC_XXX

Again, either leave the above crap out entirely or place it
below the triple-dash line.

> This introduces selected generic bitop files from kernel. We don't need minix, ext2, sched or lock based bitops. Those have been dropped.

Line wrap the log message at 70 or 72.

> Signed-off-by: Nishanth Menon <x0nishan@ti.com>
> 
> ---
>  include/asm-generic/bitops/__ffs.h   |   43 ++++++++++++++++
>  include/asm-generic/bitops/__fls.h   |   43 ++++++++++++++++


Thanks,
jdl

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-06-19 12:56 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-18 12:34 [U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops Menon, Nishanth
2008-06-18 15:30 ` Sascha Hauer
2008-06-18 15:41   ` Menon, Nishanth
2008-06-18 15:50     ` Sascha Hauer
2008-06-19  6:12       ` [U-Boot-Users] [Patch 1/3] U-Boot-V2: Bitops cleanup: introduce asm-generic bitops Menon, Nishanth
2008-06-19 12:56         ` Jon Loeliger
2008-06-19  6:13       ` [U-Boot-Users] [Patch 2/3] U-Boot-V2: Bitops cleanup: cleanup ARM bitops Menon, Nishanth
2008-06-19  6:13       ` [U-Boot-Users] [Patch 3/3] U-Boot-V2: Bitops cleanup: cleanup rest of generic_xxx functions Menon, Nishanth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox