From: Willy Tarreau Date: Tue, 5 Mar 2019 11:04:55 +0000 (+0100) Subject: MINOR: tools: implement my_flsl() X-Git-Tag: v2.0-dev2~112 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d87a67f9bc422bf41b6b81c1e99d9aebbbc18d8e;p=thirdparty%2Fhaproxy.git MINOR: tools: implement my_flsl() We already have my_ffsl() to find the lowest bit set in a word, and this patch implements the search for the highest bit set in a word. On x86 it uses the bsr instruction and on other architectures it uses an efficient implementation. --- diff --git a/include/common/standard.h b/include/common/standard.h index 87d5f88bb3..7536a6491d 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -808,7 +808,7 @@ static inline unsigned long atleast2(unsigned long a) } /* Simple ffs implementation. It returns the position of the lowest bit set to - * one. It is illegal to call it with a==0 (undefined result). + * one, starting at 1. It is illegal to call it with a==0 (undefined result). */ static inline unsigned int my_ffsl(unsigned long a) { @@ -851,6 +851,50 @@ static inline unsigned int my_ffsl(unsigned long a) return cnt; } +/* Simple fls implementation. It returns the position of the highest bit set to + * one, starting at 1. It is illegal to call it with a==0 (undefined result). + */ +static inline unsigned int my_flsl(unsigned long a) +{ + unsigned long cnt; + +#if defined(__x86_64__) + __asm__("bsr %1,%0\n" : "=r" (cnt) : "rm" (a)); + cnt++; +#else + + cnt = 1; +#if LONG_MAX > 0x7FFFFFFFUL /* 64bits */ + if (a & 0xFFFFFFFF00000000UL) { + a >>= 32; + cnt += 32; + } +#endif + if (a & 0XFFFF0000U) { + a >>= 16; + cnt += 16; + } + if (a & 0XFF00) { + a >>= 8; + cnt += 8; + } + if (a & 0xf0) { + a >>= 4; + cnt += 4; + } + if (a & 0xc) { + a >>= 2; + cnt += 2; + } + if (a & 0x2) { + a >>= 1; + cnt += 1; + } +#endif /* x86_64 */ + + return cnt; +} + /* Build a word with the lower bits set (reverse of my_popcountl) */ static inline unsigned long nbits(int bits) {