xref: /openbsd-src/sys/lib/libkern/ctzdi2.c (revision 614862c8bb76e418c62102ea04c9b99d3f680d40)
1 /*	$OpenBSD: ctzdi2.c,v 1.1 2022/12/14 23:50:31 jsg Exp $	*/
2 
3 /*
4  * Public domain.
5  * Written by Dale Rahn.
6  */
7 
8 #include <lib/libkern/libkern.h>
9 
10 /*
11  * ffsl -- vax ffs instruction with long arg
12  */
13 
14 #ifdef __LP64__
15 static int
ffsl(long mask)16 ffsl(long mask)
17 {
18 	int bit;
19 	unsigned long r = mask;
20 	static const signed char t[16] = {
21 		-60, 1, 2, 1,
22 		  3, 1, 2, 1,
23 		  4, 1, 2, 1,
24 		  3, 1, 2, 1
25 	};
26 
27 	bit = 0;
28 	if (!(r & 0xffffffff)) {
29 		bit += 32;
30 		r >>= 32;
31 	}
32 	if (!(r & 0xffff)) {
33 		bit += 16;
34 		r >>= 16;
35 	}
36 	if (!(r & 0xff)) {
37 		bit += 8;
38 		r >>= 8;
39 	}
40 	if (!(r & 0xf)) {
41 		bit += 4;
42 		r >>= 4;
43 	}
44 
45 	return (bit + t[ r & 0xf ]);
46 }
47 #else
48 static int
ffsl(long mask)49 ffsl(long mask)
50 {
51 	return ffs(mask);
52 }
53 #endif
54 
55 int
__ctzdi2(long mask)56 __ctzdi2(long mask)
57 {
58 	if (mask == 0)
59 		return 0;
60 	return ffsl(mask) - 1;
61 }
62