162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_GENERIC_BITOPS___FLS_H_
362306a36Sopenharmony_ci#define _ASM_GENERIC_BITOPS___FLS_H_
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <asm/types.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/**
862306a36Sopenharmony_ci * __fls - find last (most-significant) set bit in a long word
962306a36Sopenharmony_ci * @word: the word to search
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Undefined if no set bit exists, so code should check against 0 first.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_cistatic __always_inline unsigned long __fls(unsigned long word)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	int num = BITS_PER_LONG - 1;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#if BITS_PER_LONG == 64
1862306a36Sopenharmony_ci	if (!(word & (~0ul << 32))) {
1962306a36Sopenharmony_ci		num -= 32;
2062306a36Sopenharmony_ci		word <<= 32;
2162306a36Sopenharmony_ci	}
2262306a36Sopenharmony_ci#endif
2362306a36Sopenharmony_ci	if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
2462306a36Sopenharmony_ci		num -= 16;
2562306a36Sopenharmony_ci		word <<= 16;
2662306a36Sopenharmony_ci	}
2762306a36Sopenharmony_ci	if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
2862306a36Sopenharmony_ci		num -= 8;
2962306a36Sopenharmony_ci		word <<= 8;
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci	if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
3262306a36Sopenharmony_ci		num -= 4;
3362306a36Sopenharmony_ci		word <<= 4;
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci	if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
3662306a36Sopenharmony_ci		num -= 2;
3762306a36Sopenharmony_ci		word <<= 2;
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci	if (!(word & (~0ul << (BITS_PER_LONG-1))))
4062306a36Sopenharmony_ci		num -= 1;
4162306a36Sopenharmony_ci	return num;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
45