blob: fe6173039ce4e34524aa3f764330e6eacd20324e [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
#ifndef __BITOPS_H__
#define __BITOPS_H__
/*
* fls: find last bit set.
*/
#ifndef HAVE_FLS
static inline int fls(int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x = (x & 0xffffu) << 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x = (x & 0xffffffu) << 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x = (x & 0xfffffffu) << 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x = (x & 0x3fffffffu) << 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
r -= 1;
}
return r;
}
#endif /* HAVE_FLS */
static inline int fls64(__u64 x)
{
__u32 h = x >> 32;
if (h)
return fls(h) + 32;
return fls(x);
}
static inline unsigned fls_long(unsigned long l)
{
if (sizeof(l) == 4)
return fls(l);
return fls64(l);
}
/*
* ffz: find first zero bit.
* Result is undefined if no zero bit exists.
*/
#define ffz(x) ffs(~(x))
/*
* XFS bit manipulation routines. Repeated here so that some programs
* don't have to link in all of libxfs just to have bit manipulation.
*/
/*
* masks with n high/low bits set, 64-bit values
*/
static inline uint64_t mask64hi(int n)
{
return (uint64_t)-1 << (64 - (n));
}
static inline uint32_t mask32lo(int n)
{
return ((uint32_t)1 << (n)) - 1;
}
static inline uint64_t mask64lo(int n)
{
return ((uint64_t)1 << (n)) - 1;
}
/* Get high bit set out of 32-bit argument, -1 if none set */
static inline int highbit32(uint32_t v)
{
return fls(v) - 1;
}
/* Get high bit set out of 64-bit argument, -1 if none set */
static inline int highbit64(uint64_t v)
{
return fls64(v) - 1;
}
/* Get low bit set out of 32-bit argument, -1 if none set */
static inline int lowbit32(uint32_t v)
{
return ffs(v) - 1;
}
/* Get low bit set out of 64-bit argument, -1 if none set */
static inline int lowbit64(uint64_t v)
{
uint32_t w = (uint32_t)v;
int n = 0;
if (w) { /* lower bits */
n = ffs(w);
} else { /* upper bits */
w = (uint32_t)(v >> 32);
if (w) {
n = ffs(w);
if (n)
n += 32;
}
}
return n - 1;
}
#endif