-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbits.h
156 lines (125 loc) · 3.71 KB
/
bits.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once
#include <stdint.h>
/*
** Architecture-specific bit manipulation routines.
**
** Most modern processors provide instructions to count leading zeroes
** in a word, find the lowest and highest set bit, etc. These
** specific implementations will be used when available, falling back
** to a reasonably efficient generic implementation.
**
** bit_ffs/bit_fls returning value 0..31.
** ffs/fls return 1-32 by default, returning 0 for error.
*/
/*
** gcc 3.4 and above have builtin support, specialized for architecture.
** Some compilers masquerade as gcc; patchlevel test filters them out.
*/
#if defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
&& defined (__GNUC_PATCHLEVEL__)
inline uint32_t bit_ffs32(uint32_t word)
{
return __builtin_ffs(word) - 1;
}
inline uint32_t bit_fls32(uint32_t word)
{
const uint32_t bit = word ? 32 - __builtin_clz(word) : 0;
return bit - 1;
}
#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && defined (_M_IX86)
/* Microsoft Visual C++ support on x86/X64 architectures. */
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
#pragma intrinsic(_BitScanForward)
inline uint32_t bit_fls32(uint32_t word)
{
uint32_t index;
return _BitScanReverse(&index, word) ? index : -1;
}
inline uint32_t bit_ffs32(uint32_t word)
{
uint32_t index;
return _BitScanForward(&index, word) ? index : -1;
}
inline uint32_t bit_fls64(uint64_t word)
{
uint32_t index;
if (_BitScanReverse(&index, word>>32)) return index+32;
return _BitScanReverse(&index, word&0xFFFFFFFF) ? index : UINT32_MAX;
}
inline uint32_t bit_ffs64(uint64_t word)
{
uint32_t index;
if (_BitScanForward(&index, word&0xFFFFFFFF)) return index;
return _BitScanForward(&index, word>>32) ? index+32 : UINT32_MAX;
}
#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && defined (_M_X64)
/* Microsoft Visual C++ support on x86/X64 architectures. */
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
#pragma intrinsic(_BitScanForward)
inline uint32_t bit_fls32(uint32_t word)
{
uint32_t index;
return _BitScanReverse(&index, word) ? index : -1;
}
inline uint32_t bit_ffs32(uint32_t word)
{
uint32_t index;
return _BitScanForward(&index, word) ? index : -1;
}
inline uint32_t bit_fls64(uint64_t word)
{
uint32_t index;
return _BitScanReverse64(&index, word) ? index : UINT32_MAX;
}
inline uint32_t bit_ffs64(uint64_t word)
{
uint32_t index;
return _BitScanForward64(&index, word) ? index : UINT32_MAX;
}
#elif defined (__ARMCC_VERSION)
/* RealView Compilation Tools for ARM */
inline uint32_t bit_ffs32(uint32_t word)
{
const uint32_t reverse = word & (~word + 1);
const uint32_t bit = 32 - __clz(reverse);
return bit - 1;
}
inline uint32_t bit_fls32(uint32_t word)
{
const uint32_t bit = word ? 32 - __clz(word) : 0;
return bit - 1;
}
#else
/* Fall back to generic implementation. */
inline uint32_t bit_fls_generic(uint32_t word)
{
uint32_t bit = 32;
if (!word) bit -= 1;
if (!(word & 0xffff0000)) { word <<= 16; bit -= 16; }
if (!(word & 0xff000000)) { word <<= 8; bit -= 8; }
if (!(word & 0xf0000000)) { word <<= 4; bit -= 4; }
if (!(word & 0xc0000000)) { word <<= 2; bit -= 2; }
if (!(word & 0x80000000)) { word <<= 1; bit -= 1; }
return bit;
}
/* Implement ffs in terms of fls. */
inline uint32_t bit_ffs32(uint32_t word)
{
return bit_fls_generic(word & (~word + 1)) - 1;
}
inline uint32_t bit_fls32(uint32_t word)
{
return bit_fls_generic(word) - 1;
}
#endif
inline uint32_t bit_is_pow2(uint32_t x)
{
return (x != 0) && ((x & (x - 1)) == 0);
}
inline uint32_t bit_align_up(uint32_t size, uint32_t align)
{
assert(bit_is_pow2(align));
return (size + (align - 1)) & ~(align - 1);
}