comparison SDL3/SDL_intrin.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 /* WIKI CATEGORY: Intrinsics */
23
24 /**
25 * # CategoryIntrinsics
26 *
27 * SDL does some preprocessor gymnastics to determine if any CPU-specific
28 * compiler intrinsics are available, as this is not necessarily an easy thing
29 * to calculate, and sometimes depends on quirks of a system, versions of
30 * build tools, and other external forces.
31 *
32 * Apps including SDL's headers will be able to check consistent preprocessor
33 * definitions to decide if it's safe to use compiler intrinsics for a
34 * specific CPU architecture. This check only tells you that the compiler is
35 * capable of using those intrinsics; at runtime, you should still check if
36 * they are available on the current system with the
37 * [CPU info functions](https://wiki.libsdl.org/SDL3/CategoryCPUInfo)
38 * , such as SDL_HasSSE() or SDL_HasNEON(). Otherwise, the process might crash
39 * for using an unsupported CPU instruction.
40 *
41 * SDL only sets preprocessor defines for CPU intrinsics if they are
42 * supported, so apps should check with `#ifdef` and not `#if`.
43 *
44 * SDL will also include the appropriate instruction-set-specific support
45 * headers, so if SDL decides to define SDL_SSE2_INTRINSICS, it will also
46 * `#include <emmintrin.h>` as well.
47 */
48
49 #ifndef SDL_intrin_h_
50 #define SDL_intrin_h_
51
52 #include <SDL3/SDL_stdinc.h>
53
54 #ifdef SDL_WIKI_DOCUMENTATION_SECTION
55
56 /**
57 * Defined if (and only if) the compiler supports Loongarch LSX intrinsics.
58 *
59 * If this macro is defined, SDL will have already included `<lsxintrin.h>`
60 *
61 * \since This macro is available since SDL 3.2.0.
62 *
63 * \sa SDL_LASX_INTRINSICS
64 */
65 #define SDL_LSX_INTRINSICS 1
66
67 /**
68 * Defined if (and only if) the compiler supports Loongarch LSX intrinsics.
69 *
70 * If this macro is defined, SDL will have already included `<lasxintrin.h>`
71 *
72 * \since This macro is available since SDL 3.2.0.
73 *
74 * \sa SDL_LASX_INTRINSICS
75 */
76 #define SDL_LASX_INTRINSICS 1
77
78 /**
79 * Defined if (and only if) the compiler supports ARM NEON intrinsics.
80 *
81 * If this macro is defined, SDL will have already included `<armintr.h>`
82 * `<arm_neon.h>`, `<arm64intr.h>`, and `<arm64_neon.h>`, as appropriate.
83 *
84 * \since This macro is available since SDL 3.2.0.
85 */
86 #define SDL_NEON_INTRINSICS 1
87
88 /**
89 * Defined if (and only if) the compiler supports PowerPC Altivec intrinsics.
90 *
91 * If this macro is defined, SDL will have already included `<altivec.h>`
92 *
93 * \since This macro is available since SDL 3.2.0.
94 */
95 #define SDL_ALTIVEC_INTRINSICS 1
96
97 /**
98 * Defined if (and only if) the compiler supports Intel MMX intrinsics.
99 *
100 * If this macro is defined, SDL will have already included `<mmintrin.h>`
101 *
102 * \since This macro is available since SDL 3.2.0.
103 *
104 * \sa SDL_SSE_INTRINSICS
105 */
106 #define SDL_MMX_INTRINSICS 1
107
108 /**
109 * Defined if (and only if) the compiler supports Intel SSE intrinsics.
110 *
111 * If this macro is defined, SDL will have already included `<xmmintrin.h>`
112 *
113 * \since This macro is available since SDL 3.2.0.
114 *
115 * \sa SDL_SSE2_INTRINSICS
116 * \sa SDL_SSE3_INTRINSICS
117 * \sa SDL_SSE4_1_INTRINSICS
118 * \sa SDL_SSE4_2_INTRINSICS
119 */
120 #define SDL_SSE_INTRINSICS 1
121
122 /**
123 * Defined if (and only if) the compiler supports Intel SSE2 intrinsics.
124 *
125 * If this macro is defined, SDL will have already included `<emmintrin.h>`
126 *
127 * \since This macro is available since SDL 3.2.0.
128 *
129 * \sa SDL_SSE_INTRINSICS
130 * \sa SDL_SSE3_INTRINSICS
131 * \sa SDL_SSE4_1_INTRINSICS
132 * \sa SDL_SSE4_2_INTRINSICS
133 */
134 #define SDL_SSE2_INTRINSICS 1
135
136 /**
137 * Defined if (and only if) the compiler supports Intel SSE3 intrinsics.
138 *
139 * If this macro is defined, SDL will have already included `<pmmintrin.h>`
140 *
141 * \since This macro is available since SDL 3.2.0.
142 *
143 * \sa SDL_SSE_INTRINSICS
144 * \sa SDL_SSE2_INTRINSICS
145 * \sa SDL_SSE4_1_INTRINSICS
146 * \sa SDL_SSE4_2_INTRINSICS
147 */
148 #define SDL_SSE3_INTRINSICS 1
149
150 /**
151 * Defined if (and only if) the compiler supports Intel SSE4.1 intrinsics.
152 *
153 * If this macro is defined, SDL will have already included `<smmintrin.h>`
154 *
155 * \since This macro is available since SDL 3.2.0.
156 *
157 * \sa SDL_SSE_INTRINSICS
158 * \sa SDL_SSE2_INTRINSICS
159 * \sa SDL_SSE3_INTRINSICS
160 * \sa SDL_SSE4_2_INTRINSICS
161 */
162 #define SDL_SSE4_1_INTRINSICS 1
163
164 /**
165 * Defined if (and only if) the compiler supports Intel SSE4.2 intrinsics.
166 *
167 * If this macro is defined, SDL will have already included `<nmmintrin.h>`
168 *
169 * \since This macro is available since SDL 3.2.0.
170 *
171 * \sa SDL_SSE_INTRINSICS
172 * \sa SDL_SSE2_INTRINSICS
173 * \sa SDL_SSE3_INTRINSICS
174 * \sa SDL_SSE4_1_INTRINSICS
175 */
176 #define SDL_SSE4_2_INTRINSICS 1
177
178 /**
179 * Defined if (and only if) the compiler supports Intel AVX intrinsics.
180 *
181 * If this macro is defined, SDL will have already included `<immintrin.h>`
182 *
183 * \since This macro is available since SDL 3.2.0.
184 *
185 * \sa SDL_AVX2_INTRINSICS
186 * \sa SDL_AVX512F_INTRINSICS
187 */
188 #define SDL_AVX_INTRINSICS 1
189
190 /**
191 * Defined if (and only if) the compiler supports Intel AVX2 intrinsics.
192 *
193 * If this macro is defined, SDL will have already included `<immintrin.h>`
194 *
195 * \since This macro is available since SDL 3.2.0.
196 *
197 * \sa SDL_AVX_INTRINSICS
198 * \sa SDL_AVX512F_INTRINSICS
199 */
200 #define SDL_AVX2_INTRINSICS 1
201
202 /**
203 * Defined if (and only if) the compiler supports Intel AVX-512F intrinsics.
204 *
205 * AVX-512F is also sometimes referred to as "AVX-512 Foundation."
206 *
207 * If this macro is defined, SDL will have already included `<immintrin.h>`
208 *
209 * \since This macro is available since SDL 3.2.0.
210 *
211 * \sa SDL_AVX_INTRINSICS
212 * \sa SDL_AVX2_INTRINSICS
213 */
214 #define SDL_AVX512F_INTRINSICS 1
215 #endif
216
217 /* Need to do this here because intrin.h has C++ code in it */
218 /* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
219 #if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))
220 #ifdef __clang__
221 /* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
222 so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
223 #ifndef __PRFCHWINTRIN_H
224 #define __PRFCHWINTRIN_H
225 static __inline__ void __attribute__((__always_inline__, __nodebug__))
226 _m_prefetch(void *__P)
227 {
228 __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
229 }
230 #endif /* __PRFCHWINTRIN_H */
231 #endif /* __clang__ */
232 #include <intrin.h>
233
234 #elif defined(__MINGW64_VERSION_MAJOR)
235 #include <intrin.h>
236 #if defined(__ARM_NEON) && !defined(SDL_DISABLE_NEON)
237 # define SDL_NEON_INTRINSICS 1
238 # include <arm_neon.h>
239 #endif
240
241 #else
242 /* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC to have it included. */
243 #if defined(__ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC)
244 #define SDL_ALTIVEC_INTRINSICS 1
245 #include <altivec.h>
246 #endif
247 #ifndef SDL_DISABLE_NEON
248 # ifdef __ARM_NEON
249 # define SDL_NEON_INTRINSICS 1
250 # include <arm_neon.h>
251 # elif defined(SDL_PLATFORM_WINDOWS)
252 /* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */
253 # ifdef _M_ARM
254 # define SDL_NEON_INTRINSICS 1
255 # include <armintr.h>
256 # include <arm_neon.h>
257 # define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
258 # endif
259 # if defined (_M_ARM64)
260 # define SDL_NEON_INTRINSICS 1
261 # include <arm64intr.h>
262 # include <arm64_neon.h>
263 # define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
264 # define __ARM_ARCH 8
265 # endif
266 # endif
267 #endif
268 #endif /* compiler version */
269
270 #ifdef SDL_WIKI_DOCUMENTATION_SECTION
271
272 /**
273 * A macro to decide if the compiler supports `__attribute__((target))`.
274 *
275 * Even though this is defined in SDL's public headers, it is generally not
276 * used directly by apps. Apps should probably just use SDL_TARGETING
277 * directly, instead.
278 *
279 * \since This macro is available since SDL 3.2.0.
280 *
281 * \sa SDL_TARGETING
282 */
283 #define SDL_HAS_TARGET_ATTRIBS
284 #elif defined(__loongarch64) && defined(__GNUC__) && (__GNUC__ >= 15)
285 /* LoongArch requires GCC 15+ for target attribute support */
286 # define SDL_HAS_TARGET_ATTRIBS
287 #elif defined(__clang__) && defined(__has_attribute)
288 # if __has_attribute(target)
289 # define SDL_HAS_TARGET_ATTRIBS
290 # endif
291 #elif defined(__GNUC__) && !defined(__loongarch64) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */
292 # define SDL_HAS_TARGET_ATTRIBS
293 #elif defined(__ICC) && __ICC >= 1600
294 # define SDL_HAS_TARGET_ATTRIBS
295 #endif
296
297
298 #ifdef SDL_WIKI_DOCUMENTATION_SECTION
299
300 /**
301 * A macro to tag a function as targeting a specific CPU architecture.
302 *
303 * This is a hint to the compiler that a function should be built with support
304 * for a CPU instruction set that might be different than the rest of the
305 * program.
306 *
307 * The particulars of this are explained in the GCC documentation:
308 *
309 * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-target-function-attribute
310 *
311 * An example of using this feature is to turn on SSE2 support for a specific
312 * function, even if the rest of the source code is not compiled to use SSE2
313 * code:
314 *
315 * ```c
316 * #ifdef SDL_SSE2_INTRINSICS
317 * static void SDL_TARGETING("sse2") DoSomethingWithSSE2(char *x) {
318 * ...use SSE2 intrinsic functions, etc...
319 * }
320 * #endif
321 *
322 * // later...
323 * #ifdef SDL_SSE2_INTRINSICS
324 * if (SDL_HasSSE2()) {
325 * DoSomethingWithSSE2(str);
326 * }
327 * #endif
328 * ```
329 *
330 * The application is, on a whole, built without SSE2 instructions, so it will
331 * run on Intel machines that don't support SSE2. But then at runtime, it
332 * checks if the system supports the instructions, and then calls into a
333 * function that uses SSE2 opcodes. The ifdefs make sure that this code isn't
334 * used on platforms that don't have SSE2 at all.
335 *
336 * On compilers without target support, this is defined to nothing.
337 *
338 * This symbol is used by SDL internally, but apps and other libraries are
339 * welcome to use it for their own interfaces as well.
340 *
341 * \since This macro is available since SDL 3.2.0.
342 */
343 #define SDL_TARGETING(x) __attribute__((target(x)))
344
345 #elif defined(SDL_HAS_TARGET_ATTRIBS)
346 # define SDL_TARGETING(x) __attribute__((target(x)))
347 #else
348 # define SDL_TARGETING(x)
349 #endif
350
351 #ifdef __loongarch64
352 # ifndef SDL_DISABLE_LSX
353 # define SDL_LSX_INTRINSICS 1
354 # include <lsxintrin.h>
355 # endif
356 # ifndef SDL_DISABLE_LASX
357 # define SDL_LASX_INTRINSICS 1
358 # include <lasxintrin.h>
359 # endif
360 #endif
361
362 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
363 # if ((defined(_MSC_VER) && !defined(_M_X64)) || defined(__MMX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_MMX)
364 # define SDL_MMX_INTRINSICS 1
365 # include <mmintrin.h>
366 # endif
367 # if (defined(_MSC_VER) || defined(__SSE__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE)
368 # define SDL_SSE_INTRINSICS 1
369 # include <xmmintrin.h>
370 # endif
371 # if (defined(_MSC_VER) || defined(__SSE2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE2)
372 # define SDL_SSE2_INTRINSICS 1
373 # include <emmintrin.h>
374 # endif
375 # if (defined(_MSC_VER) || defined(__SSE3__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE3)
376 # define SDL_SSE3_INTRINSICS 1
377 # include <pmmintrin.h>
378 # endif
379 # if (defined(_MSC_VER) || defined(__SSE4_1__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE4_1)
380 # define SDL_SSE4_1_INTRINSICS 1
381 # include <smmintrin.h>
382 # endif
383 # if (defined(_MSC_VER) || defined(__SSE4_2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE4_2)
384 # define SDL_SSE4_2_INTRINSICS 1
385 # include <nmmintrin.h>
386 # endif
387 # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX__) && !defined(SDL_DISABLE_AVX)
388 # define SDL_DISABLE_AVX /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */
389 # endif
390 # if (defined(_MSC_VER) || defined(__AVX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX)
391 # define SDL_AVX_INTRINSICS 1
392 # include <immintrin.h>
393 # endif
394 # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX2__) && !defined(SDL_DISABLE_AVX2)
395 # define SDL_DISABLE_AVX2 /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */
396 # endif
397 # if (defined(_MSC_VER) || defined(__AVX2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX2)
398 # define SDL_AVX2_INTRINSICS 1
399 # include <immintrin.h>
400 # endif
401 # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX512F__) && !defined(SDL_DISABLE_AVX512F)
402 # define SDL_DISABLE_AVX512F /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */
403 # endif
404 # if (defined(_MSC_VER) || defined(__AVX512F__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX512F)
405 # define SDL_AVX512F_INTRINSICS 1
406 # include <immintrin.h>
407 # endif
408 #endif /* defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) */
409
410 #endif /* SDL_intrin_h_ */