[U-Boot] [PATCH v9 1/4] include: Add log2 and generic bitops header files
Jagan Teki
jteki at openedev.com
Thu Oct 22 12:25:12 CEST 2015
On 20 October 2015 at 18:33, Fabio Estevam <fabio.estevam at freescale.com> wrote:
> Use the log2 and generic bitops header files directly from the kernel.
Pls- add separate patches for log2 and biptops, do remember that use
same Linux approach but don't add unneeded definitions now will add
based on the need.
>
> Based on the headers froom kernel 4.2.3.
>
> Signed-off-by: Fabio Estevam <fabio.estevam at freescale.com>
> ---
> Changes since v8:
> - Do not mix generic versus arch specific header (Jagan)
> - Build tested on ARM, m68k, powerpc, bfin, microblaze, sh and x86
>
> arch/arm/include/asm/bitops.h | 98 +++++++++++++++++
> arch/blackfin/include/asm/bitops.h | 4 +
> arch/m68k/include/asm/bitops.h | 4 +
> arch/microblaze/include/asm/bitops.h | 4 +
> arch/powerpc/cpu/mpc83xx/law.c | 4 +-
> arch/powerpc/cpu/mpc85xx/tlb.c | 2 +
> arch/powerpc/cpu/mpc8xxx/law.c | 5 +-
> arch/powerpc/include/asm/bitops.h | 43 +-------
> arch/sh/include/asm/bitops.h | 5 +
> arch/x86/include/asm/bitops.h | 6 +-
> drivers/pci/fsl_pci_init.c | 1 +
> 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/fls.h | 41 +++++++
> include/asm-generic/bitops/fls64.h | 36 ++++++
> include/linux/bitops.h | 26 +++++
> include/linux/log2.h | 205 +++++++++++++++++++++++++++++++++++
> 18 files changed, 566 insertions(+), 45 deletions(-)
> create mode 100644 include/asm-generic/bitops/__ffs.h
> create mode 100644 include/asm-generic/bitops/__fls.h
> create mode 100644 include/asm-generic/bitops/ffs.h
> create mode 100644 include/asm-generic/bitops/fls.h
> create mode 100644 include/asm-generic/bitops/fls64.h
> create mode 100644 include/linux/log2.h
>
> diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
> index 9b78043..cbc07ae 100644
> --- a/arch/arm/include/asm/bitops.h
> +++ b/arch/arm/include/asm/bitops.h
> @@ -190,4 +190,102 @@ found_middle:
>
> #endif /* __KERNEL__ */
>
> +#if __LINUX_ARM_ARCH__ < 5
> +
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/__ffs.h>
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/ffs.h>
> +
> +#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. __clz returns
> + * the number of leading zeros, zero input will return 32, and
> + * 0x80000000 will return 0.
> + */
> +static inline unsigned int __clz(unsigned int x)
> +{
> + unsigned int ret;
> +
> + asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
> +
> + return ret;
> +}
> +
> +/*
> + * fls() returns zero if the input is zero, otherwise returns the bit
> + * position of the last set bit, where the LSB is 1 and MSB is 32.
> + */
> +static inline int fls(int x)
> +{
> + if (__builtin_constant_p(x))
> + return constant_fls(x);
> +
> + return 32 - __clz(x);
> +}
> +
> +/*
> + * __fls() returns the bit position of the last bit set, where the
> + * LSB is 0 and MSB is 31. Zero input is undefined.
> + */
> +static inline unsigned long __fls(unsigned long x)
> +{
> + return fls(x) - 1;
> +}
> +
> +/*
> + * ffs() returns zero if the input was zero, otherwise returns the bit
> + * position of the first set bit, where the LSB is 1 and MSB is 32.
> + */
> +static inline int ffs(int x)
> +{
> + return fls(x & -x);
> +}
> +
> +/*
> + * __ffs() returns the bit position of the first bit set, where the
> + * LSB is 0 and MSB is 31. Zero input is undefined.
> + */
> +static inline unsigned long __ffs(unsigned long x)
> +{
> + return ffs(x) - 1;
> +}
> +
> +#define ffz(x) __ffs( ~(x) )
> +
> +#endif
> +
> +#include <asm-generic/bitops/fls64.h>
> +
> #endif /* _ARM_BITOPS_H */
> diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
> index cd7e356..6cde6db 100644
> --- a/arch/blackfin/include/asm/bitops.h
> +++ b/arch/blackfin/include/asm/bitops.h
> @@ -15,6 +15,10 @@
>
> #include <asm/byteorder.h>
> #include <asm/system.h>
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/fls64.h>
> +#include <asm-generic/bitops/__ffs.h>
>
> #ifdef __KERNEL__
> /*
> diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
> index f9c434b..69ea26a 100644
> --- a/arch/m68k/include/asm/bitops.h
> +++ b/arch/m68k/include/asm/bitops.h
> @@ -6,6 +6,10 @@
> #define _M68K_BITOPS_H
>
> #include <asm/byteorder.h>
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/fls64.h>
> +#include <asm-generic/bitops/__ffs.h>
>
> extern void set_bit(int nr, volatile void *addr);
> extern void clear_bit(int nr, volatile void *addr);
> diff --git a/arch/microblaze/include/asm/bitops.h b/arch/microblaze/include/asm/bitops.h
> index 0ac78d7..d24f2cf 100644
> --- a/arch/microblaze/include/asm/bitops.h
> +++ b/arch/microblaze/include/asm/bitops.h
> @@ -7,6 +7,10 @@
>
> #include <asm/byteorder.h> /* swab32 */
> #include <asm/system.h> /* save_flags */
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/fls64.h>
> +#include <asm-generic/bitops/__ffs.h>
>
> #ifdef __KERNEL__
> /*
> diff --git a/arch/powerpc/cpu/mpc83xx/law.c b/arch/powerpc/cpu/mpc83xx/law.c
> index 66c88b6..d8173f4 100644
> --- a/arch/powerpc/cpu/mpc83xx/law.c
> +++ b/arch/powerpc/cpu/mpc83xx/law.c
> @@ -20,7 +20,7 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
> if (start == 0)
> start_align = 1ull << (LAW_SIZE_2G + 1);
> else
> - start_align = 1ull << (ffs64(start) - 1);
> + start_align = 1ull << (__ffs64(start) - 1);
> law_sz = min(start_align, sz);
> law_sz_enc = __ilog2_u64(law_sz) - 1;
>
> @@ -40,7 +40,7 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
> if (sz) {
> start += law_sz;
>
> - start_align = 1ull << (ffs64(start) - 1);
> + start_align = 1ull << (__ffs64(start) - 1);
> law_sz = min(start_align, sz);
> law_sz_enc = __ilog2_u64(law_sz) - 1;
> ecm = &immap->sysconf.ddrlaw[1];
> diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c
> index 8e0508f..cf31eb2 100644
> --- a/arch/powerpc/cpu/mpc85xx/tlb.c
> +++ b/arch/powerpc/cpu/mpc85xx/tlb.c
> @@ -14,6 +14,8 @@
> #include <addr_map.h>
> #endif
>
> +#include <linux/log2.h>
> +
> DECLARE_GLOBAL_DATA_PTR;
>
> void invalidate_tlb(u8 tlb)
> diff --git a/arch/powerpc/cpu/mpc8xxx/law.c b/arch/powerpc/cpu/mpc8xxx/law.c
> index 33d53a8..24baad4 100644
> --- a/arch/powerpc/cpu/mpc8xxx/law.c
> +++ b/arch/powerpc/cpu/mpc8xxx/law.c
> @@ -11,6 +11,7 @@
> #include <linux/compiler.h>
> #include <asm/fsl_law.h>
> #include <asm/io.h>
> +#include <linux/log2.h>
>
> DECLARE_GLOBAL_DATA_PTR;
>
> @@ -187,7 +188,7 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
> if (start == 0)
> start_align = 1ull << (LAW_SIZE_32G + 1);
> else
> - start_align = 1ull << (ffs64(start) - 1);
> + start_align = 1ull << (__ffs64(start) - 1);
> law_sz = min(start_align, sz);
> law_sz_enc = __ilog2_u64(law_sz) - 1;
>
> @@ -202,7 +203,7 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
> if (sz) {
> start += law_sz;
>
> - start_align = 1ull << (ffs64(start) - 1);
> + start_align = 1ull << (__ffs64(start) - 1);
> law_sz = min(start_align, sz);
> law_sz_enc = __ilog2_u64(law_sz) - 1;
>
> diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
> index a6bcf3c..a70bbba 100644
> --- a/arch/powerpc/include/asm/bitops.h
> +++ b/arch/powerpc/include/asm/bitops.h
> @@ -6,6 +6,7 @@
> #define _PPC_BITOPS_H
>
> #include <asm/byteorder.h>
> +#include <asm-generic/bitops/__ffs.h>
>
> extern void set_bit(int nr, volatile void *addr);
> extern void clear_bit(int nr, volatile void *addr);
> @@ -179,46 +180,6 @@ static __inline__ int fls(unsigned int x)
> }
> #define PLATFORM_FLS
>
> -/**
> - * 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 __ilog2(x) + 1;
> -}
> -#else
> -#error BITS_PER_LONG not 32 or 64
> -#endif
> -
> -static inline int __ilog2_u64(u64 n)
> -{
> - return fls64(n) - 1;
> -}
> -
> -static inline int ffs64(u64 x)
> -{
> - return __ilog2_u64(x & -x) + 1ull;
> -}
> -
> #ifdef __KERNEL__
>
> /*
> @@ -232,6 +193,8 @@ extern __inline__ int ffs(int x)
> }
> #define PLATFORM_FFS
>
> +#include <asm-generic/bitops/fls64.h>
> +
> /*
> * hweightN: returns the hamming weight (i.e. the number
> * of bits set) of a N-bit word
> diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
> index c57d628..8cb8385 100644
> --- a/arch/sh/include/asm/bitops.h
> +++ b/arch/sh/include/asm/bitops.h
> @@ -1,6 +1,11 @@
> #ifndef __ASM_SH_BITOPS_H
> #define __ASM_SH_BITOPS_H
>
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/fls64.h>
> +#include <asm-generic/bitops/__ffs.h>
> +
> #ifdef __KERNEL__
> #include <asm/irqflags.h>
> /* For __swab32 */
> diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> index 5a7e4cb..a1622ae 100644
> --- a/arch/x86/include/asm/bitops.h
> +++ b/arch/x86/include/asm/bitops.h
> @@ -22,6 +22,11 @@
>
> #define ADDR (*(volatile long *) addr)
>
> +#include <asm-generic/bitops/fls.h>
> +#include <asm-generic/bitops/__fls.h>
> +#include <asm-generic/bitops/fls64.h>
> +#include <asm-generic/bitops/__ffs.h>
> +
> /**
> * set_bit - Atomically set a bit in memory
> * @nr: the bit to set
> @@ -349,7 +354,6 @@ static __inline__ int ffs(int x)
> "1:" : "=r" (r) : "g" (x));
> return r+1;
> }
> -#define PLATFORM_FFS
>
> static inline int __ilog2(unsigned int x)
> {
> diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
> index 52792dc..27daf6d 100644
> --- a/drivers/pci/fsl_pci_init.c
> +++ b/drivers/pci/fsl_pci_init.c
> @@ -7,6 +7,7 @@
> #include <common.h>
> #include <malloc.h>
> #include <asm/fsl_serdes.h>
> +#include <linux/log2.h>
>
> DECLARE_GLOBAL_DATA_PTR;
>
> diff --git a/include/asm-generic/bitops/__ffs.h b/include/asm-generic/bitops/__ffs.h
> new file mode 100644
> index 0000000..9a3274a
> --- /dev/null
> +++ b/include/asm-generic/bitops/__ffs.h
> @@ -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_ */
> diff --git a/include/asm-generic/bitops/__fls.h b/include/asm-generic/bitops/__fls.h
> new file mode 100644
> index 0000000..be24465
> --- /dev/null
> +++ b/include/asm-generic/bitops/__fls.h
> @@ -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_ */
> diff --git a/include/asm-generic/bitops/ffs.h b/include/asm-generic/bitops/ffs.h
> new file mode 100644
> index 0000000..fbbb43a
> --- /dev/null
> +++ b/include/asm-generic/bitops/ffs.h
> @@ -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_ */
> diff --git a/include/asm-generic/bitops/fls.h b/include/asm-generic/bitops/fls.h
> new file mode 100644
> index 0000000..850859b
> --- /dev/null
> +++ b/include/asm-generic/bitops/fls.h
> @@ -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_ */
> diff --git a/include/asm-generic/bitops/fls64.h b/include/asm-generic/bitops/fls64.h
> new file mode 100644
> index 0000000..86d403f
> --- /dev/null
> +++ b/include/asm-generic/bitops/fls64.h
> @@ -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_ */
> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> index 7d30ace..31d4d4d 100644
> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -129,6 +129,32 @@ static inline unsigned int generic_hweight8(unsigned int w)
> # define fls generic_fls
> #endif
>
> +static inline unsigned fls_long(unsigned long l)
> +{
> + if (sizeof(l) == 4)
> + return fls(l);
> + return fls64(l);
> +}
> +
> +/**
> + * __ffs64 - find first set bit in a 64 bit word
> + * @word: The 64 bit word
> + *
> + * On 64 bit arches this is a synomyn for __ffs
> + * The result is not defined if no bits are set, so check that @word
> + * is non-zero before calling this.
> + */
> +static inline unsigned long __ffs64(u64 word)
> +{
> +#if BITS_PER_LONG == 32
> + if (((u32)word) == 0UL)
> + return __ffs((u32)(word >> 32)) + 32;
> +#elif BITS_PER_LONG != 64
> +#error BITS_PER_LONG not 32 or 64
> +#endif
> + return __ffs((unsigned long)word);
> +}
> +
> /**
> * __set_bit - Set a bit in memory
> * @nr: the bit to set
> diff --git a/include/linux/log2.h b/include/linux/log2.h
> new file mode 100644
> index 0000000..aa1de63
> --- /dev/null
> +++ b/include/linux/log2.h
> @@ -0,0 +1,205 @@
> +/* Integer base 2 logarithm calculation
> + *
> + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowells at redhat.com)
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef _LINUX_LOG2_H
> +#define _LINUX_LOG2_H
> +
> +#include <linux/types.h>
> +#include <linux/bitops.h>
> +
> +/*
> + * deal with unrepresentable constant logarithms
> + */
> +extern __attribute__((const, noreturn))
> +int ____ilog2_NaN(void);
> +
> +/*
> + * non-constant log of base 2 calculators
> + * - the arch may override these in asm/bitops.h if they can be implemented
> + * more efficiently than using fls() and fls64()
> + * - the arch is not required to handle n==0 if implementing the fallback
> + */
> +#ifndef CONFIG_ARCH_HAS_ILOG2_U32
> +static inline __attribute__((const))
> +int __ilog2_u32(u32 n)
> +{
> + return fls(n) - 1;
> +}
> +#endif
> +
> +#ifndef CONFIG_ARCH_HAS_ILOG2_U64
> +static inline __attribute__((const))
> +int __ilog2_u64(u64 n)
> +{
> + return fls64(n) - 1;
> +}
> +#endif
> +
> +/*
> + * Determine whether some value is a power of two, where zero is
> + * *not* considered a power of two.
> + */
> +
> +static inline __attribute__((const))
> +bool is_power_of_2(unsigned long n)
> +{
> + return (n != 0 && ((n & (n - 1)) == 0));
> +}
> +
> +/*
> + * round up to nearest power of two
> + */
> +static inline __attribute__((const))
> +unsigned long __roundup_pow_of_two(unsigned long n)
> +{
> + return 1UL << fls_long(n - 1);
> +}
> +
> +/*
> + * round down to nearest power of two
> + */
> +static inline __attribute__((const))
> +unsigned long __rounddown_pow_of_two(unsigned long n)
> +{
> + return 1UL << (fls_long(n) - 1);
> +}
> +
> +/**
> + * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
> + * @n - parameter
> + *
> + * constant-capable log of base 2 calculation
> + * - this can be used to initialise global variables from constant data, hence
> + * the massive ternary operator construction
> + *
> + * selects the appropriately-sized optimised version depending on sizeof(n)
> + */
> +#define ilog2(n) \
> +( \
> + __builtin_constant_p(n) ? ( \
> + (n) < 1 ? ____ilog2_NaN() : \
> + (n) & (1ULL << 63) ? 63 : \
> + (n) & (1ULL << 62) ? 62 : \
> + (n) & (1ULL << 61) ? 61 : \
> + (n) & (1ULL << 60) ? 60 : \
> + (n) & (1ULL << 59) ? 59 : \
> + (n) & (1ULL << 58) ? 58 : \
> + (n) & (1ULL << 57) ? 57 : \
> + (n) & (1ULL << 56) ? 56 : \
> + (n) & (1ULL << 55) ? 55 : \
> + (n) & (1ULL << 54) ? 54 : \
> + (n) & (1ULL << 53) ? 53 : \
> + (n) & (1ULL << 52) ? 52 : \
> + (n) & (1ULL << 51) ? 51 : \
> + (n) & (1ULL << 50) ? 50 : \
> + (n) & (1ULL << 49) ? 49 : \
> + (n) & (1ULL << 48) ? 48 : \
> + (n) & (1ULL << 47) ? 47 : \
> + (n) & (1ULL << 46) ? 46 : \
> + (n) & (1ULL << 45) ? 45 : \
> + (n) & (1ULL << 44) ? 44 : \
> + (n) & (1ULL << 43) ? 43 : \
> + (n) & (1ULL << 42) ? 42 : \
> + (n) & (1ULL << 41) ? 41 : \
> + (n) & (1ULL << 40) ? 40 : \
> + (n) & (1ULL << 39) ? 39 : \
> + (n) & (1ULL << 38) ? 38 : \
> + (n) & (1ULL << 37) ? 37 : \
> + (n) & (1ULL << 36) ? 36 : \
> + (n) & (1ULL << 35) ? 35 : \
> + (n) & (1ULL << 34) ? 34 : \
> + (n) & (1ULL << 33) ? 33 : \
> + (n) & (1ULL << 32) ? 32 : \
> + (n) & (1ULL << 31) ? 31 : \
> + (n) & (1ULL << 30) ? 30 : \
> + (n) & (1ULL << 29) ? 29 : \
> + (n) & (1ULL << 28) ? 28 : \
> + (n) & (1ULL << 27) ? 27 : \
> + (n) & (1ULL << 26) ? 26 : \
> + (n) & (1ULL << 25) ? 25 : \
> + (n) & (1ULL << 24) ? 24 : \
> + (n) & (1ULL << 23) ? 23 : \
> + (n) & (1ULL << 22) ? 22 : \
> + (n) & (1ULL << 21) ? 21 : \
> + (n) & (1ULL << 20) ? 20 : \
> + (n) & (1ULL << 19) ? 19 : \
> + (n) & (1ULL << 18) ? 18 : \
> + (n) & (1ULL << 17) ? 17 : \
> + (n) & (1ULL << 16) ? 16 : \
> + (n) & (1ULL << 15) ? 15 : \
> + (n) & (1ULL << 14) ? 14 : \
> + (n) & (1ULL << 13) ? 13 : \
> + (n) & (1ULL << 12) ? 12 : \
> + (n) & (1ULL << 11) ? 11 : \
> + (n) & (1ULL << 10) ? 10 : \
> + (n) & (1ULL << 9) ? 9 : \
> + (n) & (1ULL << 8) ? 8 : \
> + (n) & (1ULL << 7) ? 7 : \
> + (n) & (1ULL << 6) ? 6 : \
> + (n) & (1ULL << 5) ? 5 : \
> + (n) & (1ULL << 4) ? 4 : \
> + (n) & (1ULL << 3) ? 3 : \
> + (n) & (1ULL << 2) ? 2 : \
> + (n) & (1ULL << 1) ? 1 : \
> + (n) & (1ULL << 0) ? 0 : \
> + ____ilog2_NaN() \
> + ) : \
> + (sizeof(n) <= 4) ? \
> + __ilog2_u32(n) : \
> + __ilog2_u64(n) \
> + )
> +
> +/**
> + * roundup_pow_of_two - round the given value up to nearest power of two
> + * @n - parameter
> + *
> + * round the given value up to the nearest power of two
> + * - the result is undefined when n == 0
> + * - this can be used to initialise global variables from constant data
> + */
> +#define roundup_pow_of_two(n) \
> +( \
> + __builtin_constant_p(n) ? ( \
> + (n == 1) ? 1 : \
> + (1UL << (ilog2((n) - 1) + 1)) \
> + ) : \
> + __roundup_pow_of_two(n) \
> + )
> +
> +/**
> + * rounddown_pow_of_two - round the given value down to nearest power of two
> + * @n - parameter
> + *
> + * round the given value down to the nearest power of two
> + * - the result is undefined when n == 0
> + * - this can be used to initialise global variables from constant data
> + */
> +#define rounddown_pow_of_two(n) \
> +( \
> + __builtin_constant_p(n) ? ( \
> + (1UL << ilog2(n))) : \
> + __rounddown_pow_of_two(n) \
> + )
> +
> +/**
> + * order_base_2 - calculate the (rounded up) base 2 order of the argument
> + * @n: parameter
> + *
> + * The first few values calculated by this routine:
> + * ob2(0) = 0
> + * ob2(1) = 0
> + * ob2(2) = 1
> + * ob2(3) = 2
> + * ob2(4) = 2
> + * ob2(5) = 3
> + * ... and so on.
> + */
> +
> +#define order_base_2(n) ilog2(roundup_pow_of_two(n))
> +
> +#endif /* _LINUX_LOG2_H */
> --
> 1.9.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
--
Jagan | openedev.
More information about the U-Boot
mailing list