[U-Boot-Users] [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops

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

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

Sascha,
-----Original Message----- From: Sascha Hauer [mailto:s.hauer@pengutronix.de] Sent: Wednesday, June 18, 2008 10:31 AM To: Menon, Nishanth Cc: Kamat, Nishant; u-boot-users@lists.sourceforge.net; Laurent Desnogues; philip.balister@gmail.com; dirk.behme@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

On Wed, Jun 18, 2008 at 10:41:44AM -0500, Menon, Nishanth wrote:
Sascha,
-----Original Message----- From: Sascha Hauer [mailto:s.hauer@pengutronix.de] Sent: Wednesday, June 18, 2008 10:31 AM To: Menon, Nishanth Cc: Kamat, Nishant; u-boot-users@lists.sourceforge.net; Laurent Desnogues; philip.balister@gmail.com; dirk.behme@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

Sascha, The following 3 patches are for cleaning up the bitops
-----Original Message----- From: Sascha Hauer [mailto:s.hauer@pengutronix.de] Sent: Wednesday, June 18, 2008 10:51 AM To: Menon, Nishanth Cc: Kamat, Nishant; u-boot-users@lists.sourceforge.net; Laurent Desnogues; philip.balister@gmail.com; dirk.behme@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_ */

Menon, Nishanth wrote:
Sascha, The following 3 patches are for cleaning up the bitops
-----Original Message----- From: Sascha Hauer [mailto:s.hauer@pengutronix.de] Sent: Wednesday, June 18, 2008 10:51 AM To: Menon, Nishanth Cc: Kamat, Nishant; u-boot-users@lists.sourceforge.net; Laurent Desnogues; philip.balister@gmail.com; dirk.behme@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

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 */

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__ */
participants (3)
-
Jon Loeliger
-
Menon, Nishanth
-
Sascha Hauer