1 /*
2  * Copyright (c) 2015, Wind River Systems, Inc.
3  * Copyright (c) 2017, Oticon A/S
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_
9 #define ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_
10 
11 #ifndef _ASMLANGUAGE
12 
13 #include <zephyr/types.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  *
21  * @brief find most significant bit set in a 32-bit word
22  *
23  * This routine finds the first bit set starting from the most significant bit
24  * in the argument passed in and returns the index of that bit.  Bits are
25  * numbered starting at 1 from the least significant bit.  A return value of
26  * zero indicates that the value passed is zero.
27  *
28  * @return most significant bit set, 0 if @a op is 0
29  */
30 
find_msb_set(uint32_t op)31 static ALWAYS_INLINE unsigned int find_msb_set(uint32_t op)
32 {
33 	if (op == 0) {
34 		return 0;
35 	}
36 
37 	return 32 - __builtin_clz(op);
38 }
39 
40 
41 /**
42  *
43  * @brief find least significant bit set in a 32-bit word
44  *
45  * This routine finds the first bit set starting from the least significant bit
46  * in the argument passed in and returns the index of that bit.  Bits are
47  * numbered starting at 1 from the least significant bit.  A return value of
48  * zero indicates that the value passed is zero.
49  *
50  * @return least significant bit set, 0 if @a op is 0
51  */
52 
find_lsb_set(uint32_t op)53 static ALWAYS_INLINE unsigned int find_lsb_set(uint32_t op)
54 {
55 #ifdef CONFIG_TOOLCHAIN_HAS_BUILTIN_FFS
56 	return __builtin_ffs(op);
57 
58 #else
59 	/*
60 	 * Toolchain does not have __builtin_ffs(). Leverage find_lsb_set()
61 	 * by first clearing all but the lowest set bit.
62 	 */
63 
64 	op = op ^ (op & (op - 1));
65 
66 	return find_msb_set(op);
67 #endif /* CONFIG_TOOLCHAIN_HAS_BUILTIN_FFS */
68 }
69 
70 #ifdef __cplusplus
71 }
72 #endif
73 
74 #endif /* _ASMLANGUAGE */
75 
76 #endif /* ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_ */
77