Mercurial > foo_out_sdl
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_ */ |
