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