1 /*
2  * common_defs.h
3  *
4  * Copyright 2016 Eric Biggers
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #ifndef COMMON_COMMON_DEFS_H
29 #define COMMON_COMMON_DEFS_H
30 
31 #ifdef __GNUC__
32 #  include "compiler_gcc.h"
33 #elif defined(_MSC_VER)
34 #  include "compiler_msc.h"
35 #else
36 #  pragma message("Unrecognized compiler.  Please add a header file for your compiler.  Compilation will proceed, but performance may suffer!")
37 #endif
38 
39 /* ========================================================================== */
40 /*                              Type definitions                              */
41 /* ========================================================================== */
42 
43 #include <stddef.h> /* size_t */
44 
45 #ifndef __bool_true_false_are_defined
46 #  include <stdbool.h> /* bool */
47 #endif
48 
49 /* Fixed-width integer types */
50 #include <stdint.h>
51 typedef uint8_t u8;
52 typedef uint16_t u16;
53 typedef uint32_t u32;
54 typedef uint64_t u64;
55 typedef int8_t s8;
56 typedef int16_t s16;
57 typedef int32_t s32;
58 typedef int64_t s64;
59 
60 /*
61  * Word type of the target architecture.  Use 'size_t' instead of 'unsigned
62  * long' to account for platforms such as Windows that use 32-bit 'unsigned
63  * long' on 64-bit architectures.
64  */
65 typedef size_t machine_word_t;
66 
67 /* Number of bytes in a word */
68 #define WORDBYTES	((int)sizeof(machine_word_t))
69 
70 /* Number of bits in a word */
71 #define WORDBITS	(8 * WORDBYTES)
72 
73 /* ========================================================================== */
74 /*                         Optional compiler features                         */
75 /* ========================================================================== */
76 
77 /* LIBEXPORT - export a function from a shared library */
78 #ifndef LIBEXPORT
79 #  define LIBEXPORT
80 #endif
81 
82 /* inline - suggest that a function be inlined */
83 #ifndef inline
84 #  define inline
85 #endif
86 
87 /* forceinline - force a function to be inlined, if possible */
88 #ifndef forceinline
89 #  define forceinline inline
90 #endif
91 
92 /* restrict - annotate a non-aliased pointer */
93 #ifndef restrict
94 #  define restrict
95 #endif
96 
97 /* likely(expr) - hint that an expression is usually true */
98 #ifndef likely
99 #  define likely(expr)		(expr)
100 #endif
101 
102 /* unlikely(expr) - hint that an expression is usually false */
103 #ifndef unlikely
104 #  define unlikely(expr)	(expr)
105 #endif
106 
107 /* prefetchr(addr) - prefetch into L1 cache for read */
108 #ifndef prefetchr
109 #  define prefetchr(addr)
110 #endif
111 
112 /* prefetchw(addr) - prefetch into L1 cache for write */
113 #ifndef prefetchw
114 #  define prefetchw(addr)
115 #endif
116 
117 /* Does the compiler support the 'target' function attribute? */
118 #ifndef COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE
119 #  define COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE 0
120 #endif
121 
122 /* Which targets are supported with the 'target' function attribute? */
123 #ifndef COMPILER_SUPPORTS_BMI2_TARGET
124 #  define COMPILER_SUPPORTS_BMI2_TARGET 0
125 #endif
126 #ifndef COMPILER_SUPPORTS_AVX_TARGET
127 #  define COMPILER_SUPPORTS_AVX_TARGET 0
128 #endif
129 #ifndef COMPILER_SUPPORTS_AVX512BW_TARGET
130 #  define COMPILER_SUPPORTS_AVX512BW_TARGET 0
131 #endif
132 
133 /*
134  * Which targets are supported with the 'target' function attribute and have
135  * intrinsics that work within 'target'-ed functions?
136  */
137 #ifndef COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS
138 #  define COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS 0
139 #endif
140 #ifndef COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS
141 #  define COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS 0
142 #endif
143 #ifndef COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS
144 #  define COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS 0
145 #endif
146 #ifndef COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS
147 #  define COMPILER_SUPPORTS_AVX512BW_TARGET_INTRINSICS 0
148 #endif
149 #ifndef COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS
150 #  define COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS 0
151 #endif
152 #ifndef COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS
153 #  define COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS 0
154 #endif
155 #ifndef COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS
156 #  define COMPILER_SUPPORTS_CRC32_TARGET_INTRINSICS 0
157 #endif
158 
159 /* _aligned_attribute(n) - declare that the annotated variable, or variables of
160  * the annotated type, are to be aligned on n-byte boundaries */
161 #ifndef _aligned_attribute
162 #endif
163 
164 /* ========================================================================== */
165 /*                          Miscellaneous macros                              */
166 /* ========================================================================== */
167 
168 #define ARRAY_LEN(A)		(sizeof(A) / sizeof((A)[0]))
169 #define MIN(a, b)		((a) <= (b) ? (a) : (b))
170 #define MAX(a, b)		((a) >= (b) ? (a) : (b))
171 #define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
172 #define STATIC_ASSERT(expr)	((void)sizeof(char[1 - 2 * !(expr)]))
173 #define ALIGN(n, a)		(((n) + (a) - 1) & ~((a) - 1))
174 
175 /* ========================================================================== */
176 /*                           Endianness handling                              */
177 /* ========================================================================== */
178 
179 /*
180  * CPU_IS_LITTLE_ENDIAN() - a macro which evaluates to 1 if the CPU is little
181  * endian or 0 if it is big endian.  The macro should be defined in a way such
182  * that the compiler can evaluate it at compilation time.  If not defined, a
183  * fallback is used.
184  */
185 #ifndef CPU_IS_LITTLE_ENDIAN
CPU_IS_LITTLE_ENDIAN(void)186 static forceinline int CPU_IS_LITTLE_ENDIAN(void)
187 {
188 	union {
189 		unsigned int v;
190 		unsigned char b;
191 	} u;
192 	u.v = 1;
193 	return u.b;
194 }
195 #endif
196 
197 /* bswap16(n) - swap the bytes of a 16-bit integer */
198 #ifndef bswap16
bswap16(u16 n)199 static forceinline u16 bswap16(u16 n)
200 {
201 	return (n << 8) | (n >> 8);
202 }
203 #endif
204 
205 /* bswap32(n) - swap the bytes of a 32-bit integer */
206 #ifndef bswap32
bswap32(u32 n)207 static forceinline u32 bswap32(u32 n)
208 {
209 	return ((n & 0x000000FF) << 24) |
210 	       ((n & 0x0000FF00) << 8) |
211 	       ((n & 0x00FF0000) >> 8) |
212 	       ((n & 0xFF000000) >> 24);
213 }
214 #endif
215 
216 /* bswap64(n) - swap the bytes of a 64-bit integer */
217 #ifndef bswap64
bswap64(u64 n)218 static forceinline u64 bswap64(u64 n)
219 {
220 	return ((n & 0x00000000000000FF) << 56) |
221 	       ((n & 0x000000000000FF00) << 40) |
222 	       ((n & 0x0000000000FF0000) << 24) |
223 	       ((n & 0x00000000FF000000) << 8) |
224 	       ((n & 0x000000FF00000000) >> 8) |
225 	       ((n & 0x0000FF0000000000) >> 24) |
226 	       ((n & 0x00FF000000000000) >> 40) |
227 	       ((n & 0xFF00000000000000) >> 56);
228 }
229 #endif
230 
231 #define le16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap16(n))
232 #define le32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap32(n))
233 #define le64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap64(n))
234 #define be16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap16(n) : (n))
235 #define be32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap32(n) : (n))
236 #define be64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap64(n) : (n))
237 
238 /* ========================================================================== */
239 /*                          Unaligned memory accesses                         */
240 /* ========================================================================== */
241 
242 /*
243  * UNALIGNED_ACCESS_IS_FAST should be defined to 1 if unaligned memory accesses
244  * can be performed efficiently on the target platform.
245  */
246 #ifndef UNALIGNED_ACCESS_IS_FAST
247 #  define UNALIGNED_ACCESS_IS_FAST 0
248 #endif
249 
250 /* ========================================================================== */
251 /*                             Bit scan functions                             */
252 /* ========================================================================== */
253 
254 /*
255  * Bit Scan Reverse (BSR) - find the 0-based index (relative to the least
256  * significant end) of the *most* significant 1 bit in the input value.  The
257  * input value must be nonzero!
258  */
259 
260 #ifndef bsr32
261 static forceinline unsigned
bsr32(u32 n)262 bsr32(u32 n)
263 {
264 	unsigned i = 0;
265 	while ((n >>= 1) != 0)
266 		i++;
267 	return i;
268 }
269 #endif
270 
271 #ifndef bsr64
272 static forceinline unsigned
bsr64(u64 n)273 bsr64(u64 n)
274 {
275 	unsigned i = 0;
276 	while ((n >>= 1) != 0)
277 		i++;
278 	return i;
279 }
280 #endif
281 
282 static forceinline unsigned
bsrw(machine_word_t n)283 bsrw(machine_word_t n)
284 {
285 	STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
286 	if (WORDBITS == 32)
287 		return bsr32(n);
288 	else
289 		return bsr64(n);
290 }
291 
292 /*
293  * Bit Scan Forward (BSF) - find the 0-based index (relative to the least
294  * significant end) of the *least* significant 1 bit in the input value.  The
295  * input value must be nonzero!
296  */
297 
298 #ifndef bsf32
299 static forceinline unsigned
bsf32(u32 n)300 bsf32(u32 n)
301 {
302 	unsigned i = 0;
303 	while ((n & 1) == 0) {
304 		i++;
305 		n >>= 1;
306 	}
307 	return i;
308 }
309 #endif
310 
311 #ifndef bsf64
312 static forceinline unsigned
bsf64(u64 n)313 bsf64(u64 n)
314 {
315 	unsigned i = 0;
316 	while ((n & 1) == 0) {
317 		i++;
318 		n >>= 1;
319 	}
320 	return i;
321 }
322 #endif
323 
324 static forceinline unsigned
bsfw(machine_word_t n)325 bsfw(machine_word_t n)
326 {
327 	STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
328 	if (WORDBITS == 32)
329 		return bsf32(n);
330 	else
331 		return bsf64(n);
332 }
333 
334 #endif /* COMMON_COMMON_DEFS_H */
335