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