1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <xen/bitops.h>
4 #include <xen/init.h>
5 #include <xen/self-tests.h>
6
generic_ffsl(unsigned long x)7 unsigned int generic_ffsl(unsigned long x)
8 {
9 unsigned int r = 1;
10
11 if ( !x )
12 return 0;
13
14 BUILD_BUG_ON(BITS_PER_LONG > 64); /* Extend me when necessary. */
15
16 #if BITS_PER_LONG > 32
17 if ( !(x & 0xffffffffU) )
18 {
19 x >>= 32;
20 r += 32;
21 }
22 #endif
23 if ( !(x & 0xffff) )
24 {
25 x >>= 16;
26 r += 16;
27 }
28 if ( !(x & 0xff) )
29 {
30 x >>= 8;
31 r += 8;
32 }
33 if ( !(x & 0xf) )
34 {
35 x >>= 4;
36 r += 4;
37 }
38 if ( !(x & 3) )
39 {
40 x >>= 2;
41 r += 2;
42 }
43 if ( !(x & 1) )
44 {
45 x >>= 1;
46 r += 1;
47 }
48
49 return r;
50 }
51
52 #ifdef CONFIG_SELF_TESTS
test_generic_ffsl(void)53 static void __init __constructor test_generic_ffsl(void)
54 {
55 RUNTIME_CHECK(generic_ffsl, 0, 0);
56 RUNTIME_CHECK(generic_ffsl, 1, 1);
57 RUNTIME_CHECK(generic_ffsl, 3, 1);
58 RUNTIME_CHECK(generic_ffsl, 7, 1);
59 RUNTIME_CHECK(generic_ffsl, 6, 2);
60
61 RUNTIME_CHECK(generic_ffsl, 1UL << (BITS_PER_LONG - 1), BITS_PER_LONG);
62 #if BITS_PER_LONG > 32
63 RUNTIME_CHECK(generic_ffsl, 1UL << 32, 33);
64 RUNTIME_CHECK(generic_ffsl, 1UL << 63, 64);
65 #endif
66 }
67 #endif /* CONFIG_SELF_TESTS */
68