diff options
Diffstat (limited to 'include/osmocom')
-rw-r--r-- | include/osmocom/core/log2.h | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/include/osmocom/core/log2.h b/include/osmocom/core/log2.h index 06b20f8c..dfe9d37a 100644 --- a/include/osmocom/core/log2.h +++ b/include/osmocom/core/log2.h @@ -6,6 +6,65 @@ */ #pragma once +#define __always_inline inline __attribute__((always_inline)) + +/* from linux/asm-generic/bitops/{fls,fls64}.h - could later be enhanced + * with architecture specific optimized versions */ + +/** + * 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 __always_inline int fls(unsigned 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; +} + +/** + * 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. + */ +static __always_inline int fls64(__u64 x) +{ + __u32 h = x >> 32; + if (h) + return fls(h) + 32; + return fls(x); +} /* * non-constant log of base 2 calculators |