28
28
#include <stdlib.h>
29
29
#include <inttypes.h>
30
30
31
+ #ifdef _MSC_VER
32
+ #include <intrin.h>
33
+ #include <malloc.h>
34
+ #else
35
+ #include <alloca.h>
36
+ #endif
37
+
31
38
/* set if CPU is big endian */
32
39
#undef WORDS_BIGENDIAN
33
40
41
+ #if defined(_MSC_VER )
42
+ #define likely (x ) (x)
43
+ #define unlikely (x ) (x)
44
+ #define force_inline __forceinline
45
+ #define no_inline __declspec(noinline)
46
+ #define __maybe_unused
47
+ #define __attribute__ (x )
48
+ #define __attribute (x )
49
+ typedef intptr_t ssize_t ;
50
+ #else
34
51
#define likely (x ) __builtin_expect(!!(x), 1)
35
52
#define unlikely (x ) __builtin_expect(!!(x), 0)
36
53
#define force_inline inline __attribute__((always_inline))
37
54
#define no_inline __attribute__((noinline))
38
55
#define __maybe_unused __attribute__((unused))
56
+ #endif
39
57
40
58
#define xglue (x , y ) x ## y
41
59
#define glue (x , y ) xglue(x, y)
@@ -114,27 +132,91 @@ static inline int64_t min_int64(int64_t a, int64_t b)
114
132
/* WARNING: undefined if a = 0 */
115
133
static inline int clz32 (unsigned int a )
116
134
{
135
+ #ifdef _MSC_VER
136
+ unsigned long idx ;
137
+ _BitScanReverse (& idx , a );
138
+ return 31 ^ idx ;
139
+ #else
117
140
return __builtin_clz (a );
141
+ #endif
118
142
}
119
143
120
144
/* WARNING: undefined if a = 0 */
121
145
static inline int clz64 (uint64_t a )
122
146
{
123
- return __builtin_clzll (a );
147
+ #ifdef _MSC_VER
148
+ unsigned long where ;
149
+ // BitScanReverse scans from MSB to LSB for first set bit.
150
+ // Returns 0 if no set bit is found.
151
+ #if INTPTR_MAX >= INT64_MAX // 64-bit
152
+ if (_BitScanReverse64 (& where , a ))
153
+ return (int )(63 - where );
154
+ #else
155
+ // Scan the high 32 bits.
156
+ if (_BitScanReverse (& where , (uint32_t )(a >> 32 )))
157
+ return (int )(63 - (where + 32 )); // Create a bit offset from the MSB.
158
+ // Scan the low 32 bits.
159
+ if (_BitScanReverse (& where , (uint32_t )(a )))
160
+ return (int )(63 - where );
161
+ #endif
162
+ return 64 ; // Undefined Behavior.
163
+ #else
164
+ return __builtin_clzll (a );
165
+ #endif
124
166
}
125
167
126
168
/* WARNING: undefined if a = 0 */
127
169
static inline int ctz32 (unsigned int a )
128
170
{
171
+ #ifdef _MSC_VER
172
+ unsigned long idx ;
173
+ _BitScanForward (& idx , a );
174
+ return idx ;
175
+ #else
129
176
return __builtin_ctz (a );
177
+ #endif
130
178
}
131
179
132
180
/* WARNING: undefined if a = 0 */
133
181
static inline int ctz64 (uint64_t a )
134
182
{
135
- return __builtin_ctzll (a );
183
+ #ifdef _MSC_VER
184
+ unsigned long where ;
185
+ // Search from LSB to MSB for first set bit.
186
+ // Returns zero if no set bit is found.
187
+ #if INTPTR_MAX >= INT64_MAX // 64-bit
188
+ if (_BitScanForward64 (& where , a ))
189
+ return (int )(where );
190
+ #else
191
+ // Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
192
+ // Scan the Low Word.
193
+ if (_BitScanForward (& where , (uint32_t )(a )))
194
+ return (int )(where );
195
+ // Scan the High Word.
196
+ if (_BitScanForward (& where , (uint32_t )(a >> 32 )))
197
+ return (int )(where + 32 ); // Create a bit offset from the LSB.
198
+ #endif
199
+ return 64 ;
200
+ #else
201
+ return __builtin_ctzll (a );
202
+ #endif
136
203
}
137
204
205
+ #ifdef _MSC_VER
206
+ #pragma pack(push, 1)
207
+ struct packed_u64 {
208
+ uint64_t v ;
209
+ };
210
+
211
+ struct packed_u32 {
212
+ uint32_t v ;
213
+ };
214
+
215
+ struct packed_u16 {
216
+ uint16_t v ;
217
+ };
218
+ #pragma pack(pop)
219
+ #else
138
220
struct __attribute__((packed )) packed_u64 {
139
221
uint64_t v ;
140
222
};
@@ -146,6 +228,7 @@ struct __attribute__((packed)) packed_u32 {
146
228
struct __attribute__((packed )) packed_u16 {
147
229
uint16_t v ;
148
230
};
231
+ #endif
149
232
150
233
static inline uint64_t get_u64 (const uint8_t * tab )
151
234
{
0 commit comments