]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: implement my_flsl()
authorWilly Tarreau <w@1wt.eu>
Tue, 5 Mar 2019 11:04:55 +0000 (12:04 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 7 Mar 2019 12:48:04 +0000 (13:48 +0100)
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.

include/common/standard.h

index 87d5f88bb3c101b3e67abf078ef554f3b7a76555..7536a6491d6def62963c5ae5f9710b73334b8998 100644 (file)
@@ -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 <bits> lower bits set (reverse of my_popcountl) */
 static inline unsigned long nbits(int bits)
 {