Path: blob/master/thirdparty/sdl/include/SDL3/SDL_intrin.h
9912 views
/*1Simple DirectMedia Layer2Copyright (C) 1997-2025 Sam Lantinga <[email protected]>34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/2021/* WIKI CATEGORY: Intrinsics */2223/**24* # CategoryIntrinsics25*26* SDL does some preprocessor gymnastics to determine if any CPU-specific27* compiler intrinsics are available, as this is not necessarily an easy thing28* to calculate, and sometimes depends on quirks of a system, versions of29* build tools, and other external forces.30*31* Apps including SDL's headers will be able to check consistent preprocessor32* definitions to decide if it's safe to use compiler intrinsics for a33* specific CPU architecture. This check only tells you that the compiler is34* capable of using those intrinsics; at runtime, you should still check if35* they are available on the current system with the36* [CPU info functions](https://wiki.libsdl.org/SDL3/CategoryCPUInfo)37* , such as SDL_HasSSE() or SDL_HasNEON(). Otherwise, the process might crash38* for using an unsupported CPU instruction.39*40* SDL only sets preprocessor defines for CPU intrinsics if they are41* supported, so apps should check with `#ifdef` and not `#if`.42*43* SDL will also include the appropriate instruction-set-specific support44* headers, so if SDL decides to define SDL_SSE2_INTRINSICS, it will also45* `#include <emmintrin.h>` as well.46*/4748#ifndef SDL_intrin_h_49#define SDL_intrin_h_5051#include <SDL3/SDL_stdinc.h>5253#ifdef SDL_WIKI_DOCUMENTATION_SECTION5455/**56* Defined if (and only if) the compiler supports Loongarch LSX intrinsics.57*58* If this macro is defined, SDL will have already included `<lsxintrin.h>`59*60* \since This macro is available since SDL 3.2.0.61*62* \sa SDL_LASX_INTRINSICS63*/64#define SDL_LSX_INTRINSICS 16566/**67* Defined if (and only if) the compiler supports Loongarch LSX intrinsics.68*69* If this macro is defined, SDL will have already included `<lasxintrin.h>`70*71* \since This macro is available since SDL 3.2.0.72*73* \sa SDL_LASX_INTRINSICS74*/75#define SDL_LASX_INTRINSICS 17677/**78* Defined if (and only if) the compiler supports ARM NEON intrinsics.79*80* If this macro is defined, SDL will have already included `<armintr.h>`81* `<arm_neon.h>`, `<arm64intr.h>`, and `<arm64_neon.h>`, as appropriate.82*83* \since This macro is available since SDL 3.2.0.84*/85#define SDL_NEON_INTRINSICS 18687/**88* Defined if (and only if) the compiler supports PowerPC Altivec intrinsics.89*90* If this macro is defined, SDL will have already included `<altivec.h>`91*92* \since This macro is available since SDL 3.2.0.93*/94#define SDL_ALTIVEC_INTRINSICS 19596/**97* Defined if (and only if) the compiler supports Intel MMX intrinsics.98*99* If this macro is defined, SDL will have already included `<mmintrin.h>`100*101* \since This macro is available since SDL 3.2.0.102*103* \sa SDL_SSE_INTRINSICS104*/105#define SDL_MMX_INTRINSICS 1106107/**108* Defined if (and only if) the compiler supports Intel SSE intrinsics.109*110* If this macro is defined, SDL will have already included `<xmmintrin.h>`111*112* \since This macro is available since SDL 3.2.0.113*114* \sa SDL_SSE2_INTRINSICS115* \sa SDL_SSE3_INTRINSICS116* \sa SDL_SSE4_1_INTRINSICS117* \sa SDL_SSE4_2_INTRINSICS118*/119#define SDL_SSE_INTRINSICS 1120121/**122* Defined if (and only if) the compiler supports Intel SSE2 intrinsics.123*124* If this macro is defined, SDL will have already included `<emmintrin.h>`125*126* \since This macro is available since SDL 3.2.0.127*128* \sa SDL_SSE_INTRINSICS129* \sa SDL_SSE3_INTRINSICS130* \sa SDL_SSE4_1_INTRINSICS131* \sa SDL_SSE4_2_INTRINSICS132*/133#define SDL_SSE2_INTRINSICS 1134135/**136* Defined if (and only if) the compiler supports Intel SSE3 intrinsics.137*138* If this macro is defined, SDL will have already included `<pmmintrin.h>`139*140* \since This macro is available since SDL 3.2.0.141*142* \sa SDL_SSE_INTRINSICS143* \sa SDL_SSE2_INTRINSICS144* \sa SDL_SSE4_1_INTRINSICS145* \sa SDL_SSE4_2_INTRINSICS146*/147#define SDL_SSE3_INTRINSICS 1148149/**150* Defined if (and only if) the compiler supports Intel SSE4.1 intrinsics.151*152* If this macro is defined, SDL will have already included `<smmintrin.h>`153*154* \since This macro is available since SDL 3.2.0.155*156* \sa SDL_SSE_INTRINSICS157* \sa SDL_SSE2_INTRINSICS158* \sa SDL_SSE3_INTRINSICS159* \sa SDL_SSE4_2_INTRINSICS160*/161#define SDL_SSE4_1_INTRINSICS 1162163/**164* Defined if (and only if) the compiler supports Intel SSE4.2 intrinsics.165*166* If this macro is defined, SDL will have already included `<nmmintrin.h>`167*168* \since This macro is available since SDL 3.2.0.169*170* \sa SDL_SSE_INTRINSICS171* \sa SDL_SSE2_INTRINSICS172* \sa SDL_SSE3_INTRINSICS173* \sa SDL_SSE4_1_INTRINSICS174*/175#define SDL_SSE4_2_INTRINSICS 1176177/**178* Defined if (and only if) the compiler supports Intel AVX intrinsics.179*180* If this macro is defined, SDL will have already included `<immintrin.h>`181*182* \since This macro is available since SDL 3.2.0.183*184* \sa SDL_AVX2_INTRINSICS185* \sa SDL_AVX512F_INTRINSICS186*/187#define SDL_AVX_INTRINSICS 1188189/**190* Defined if (and only if) the compiler supports Intel AVX2 intrinsics.191*192* If this macro is defined, SDL will have already included `<immintrin.h>`193*194* \since This macro is available since SDL 3.2.0.195*196* \sa SDL_AVX_INTRINSICS197* \sa SDL_AVX512F_INTRINSICS198*/199#define SDL_AVX2_INTRINSICS 1200201/**202* Defined if (and only if) the compiler supports Intel AVX-512F intrinsics.203*204* AVX-512F is also sometimes referred to as "AVX-512 Foundation."205*206* If this macro is defined, SDL will have already included `<immintrin.h>`207*208* \since This macro is available since SDL 3.2.0.209*210* \sa SDL_AVX_INTRINSICS211* \sa SDL_AVX2_INTRINSICS212*/213#define SDL_AVX512F_INTRINSICS 1214#endif215216/* Need to do this here because intrin.h has C++ code in it */217/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */218#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))219#ifdef __clang__220/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,221so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */222#ifndef __PRFCHWINTRIN_H223#define __PRFCHWINTRIN_H224static __inline__ void __attribute__((__always_inline__, __nodebug__))225_m_prefetch(void *__P)226{227__builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);228}229#endif /* __PRFCHWINTRIN_H */230#endif /* __clang__ */231#include <intrin.h>232233#elif defined(__MINGW64_VERSION_MAJOR)234#include <intrin.h>235#if defined(__ARM_NEON) && !defined(SDL_DISABLE_NEON)236# define SDL_NEON_INTRINSICS 1237# include <arm_neon.h>238#endif239240#else241/* 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. */242#if defined(__ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC)243#define SDL_ALTIVEC_INTRINSICS 1244#include <altivec.h>245#endif246#ifndef SDL_DISABLE_NEON247# ifdef __ARM_NEON248# define SDL_NEON_INTRINSICS 1249# include <arm_neon.h>250# elif defined(SDL_PLATFORM_WINDOWS)251/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */252# ifdef _M_ARM253# define SDL_NEON_INTRINSICS 1254# include <armintr.h>255# include <arm_neon.h>256# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */257# endif258# if defined (_M_ARM64)259# define SDL_NEON_INTRINSICS 1260# include <arm64intr.h>261# include <arm64_neon.h>262# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */263# define __ARM_ARCH 8264# endif265# endif266#endif267#endif /* compiler version */268269#ifdef SDL_WIKI_DOCUMENTATION_SECTION270/**271* A macro to decide if the compiler supports `__attribute__((target))`.272*273* Even though this is defined in SDL's public headers, it is generally not274* used directly by apps. Apps should probably just use SDL_TARGETING275* directly, instead.276*277* \since This macro is available since SDL 3.2.0.278*279* \sa SDL_TARGETING280*/281#define SDL_HAS_TARGET_ATTRIBS282283#elif defined(__clang__) && defined(__has_attribute)284# if __has_attribute(target)285# define SDL_HAS_TARGET_ATTRIBS286# endif287#elif defined(__GNUC__) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */288# define SDL_HAS_TARGET_ATTRIBS289#elif defined(__ICC) && __ICC >= 1600290# define SDL_HAS_TARGET_ATTRIBS291#endif292293294#ifdef SDL_WIKI_DOCUMENTATION_SECTION295296/**297* A macro to tag a function as targeting a specific CPU architecture.298*299* This is a hint to the compiler that a function should be built with support300* for a CPU instruction set that might be different than the rest of the301* program.302*303* The particulars of this are explained in the GCC documentation:304*305* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-target-function-attribute306*307* An example of using this feature is to turn on SSE2 support for a specific308* function, even if the rest of the source code is not compiled to use SSE2309* code:310*311* ```c312* #ifdef SDL_SSE2_INTRINSICS313* static void SDL_TARGETING("sse2") DoSomethingWithSSE2(char *x) {314* ...use SSE2 intrinsic functions, etc...315* }316* #endif317*318* // later...319* #ifdef SDL_SSE2_INTRINSICS320* if (SDL_HasSSE2()) {321* DoSomethingWithSSE2(str);322* }323* #endif324* ```325*326* The application is, on a whole, built without SSE2 instructions, so it will327* run on Intel machines that don't support SSE2. But then at runtime, it328* checks if the system supports the instructions, and then calls into a329* function that uses SSE2 opcodes. The ifdefs make sure that this code isn't330* used on platforms that don't have SSE2 at all.331*332* On compilers without target support, this is defined to nothing.333*334* This symbol is used by SDL internally, but apps and other libraries are335* welcome to use it for their own interfaces as well.336*337* \since This macro is available since SDL 3.2.0.338*/339#define SDL_TARGETING(x) __attribute__((target(x)))340341#elif defined(SDL_HAS_TARGET_ATTRIBS)342# define SDL_TARGETING(x) __attribute__((target(x)))343#else344# define SDL_TARGETING(x)345#endif346347#ifdef __loongarch64348# ifndef SDL_DISABLE_LSX349# define SDL_LSX_INTRINSICS 1350# include <lsxintrin.h>351# endif352# ifndef SDL_DISABLE_LASX353# define SDL_LASX_INTRINSICS 1354# include <lasxintrin.h>355# endif356#endif357358#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)359# if ((defined(_MSC_VER) && !defined(_M_X64)) || defined(__MMX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_MMX)360# define SDL_MMX_INTRINSICS 1361# include <mmintrin.h>362# endif363# if (defined(_MSC_VER) || defined(__SSE__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE)364# define SDL_SSE_INTRINSICS 1365# include <xmmintrin.h>366# endif367# if (defined(_MSC_VER) || defined(__SSE2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE2)368# define SDL_SSE2_INTRINSICS 1369# include <emmintrin.h>370# endif371# if (defined(_MSC_VER) || defined(__SSE3__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE3)372# define SDL_SSE3_INTRINSICS 1373# include <pmmintrin.h>374# endif375# if (defined(_MSC_VER) || defined(__SSE4_1__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE4_1)376# define SDL_SSE4_1_INTRINSICS 1377# include <smmintrin.h>378# endif379# if (defined(_MSC_VER) || defined(__SSE4_2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_SSE4_2)380# define SDL_SSE4_2_INTRINSICS 1381# include <nmmintrin.h>382# endif383# if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX__) && !defined(SDL_DISABLE_AVX)384# define SDL_DISABLE_AVX /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */385# endif386# if (defined(_MSC_VER) || defined(__AVX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX)387# define SDL_AVX_INTRINSICS 1388# include <immintrin.h>389# endif390# if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX2__) && !defined(SDL_DISABLE_AVX2)391# define SDL_DISABLE_AVX2 /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */392# endif393# if (defined(_MSC_VER) || defined(__AVX2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX2)394# define SDL_AVX2_INTRINSICS 1395# include <immintrin.h>396# endif397# if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX512F__) && !defined(SDL_DISABLE_AVX512F)398# define SDL_DISABLE_AVX512F /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */399# endif400# if (defined(_MSC_VER) || defined(__AVX512F__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX512F)401# define SDL_AVX512F_INTRINSICS 1402# include <immintrin.h>403# endif404#endif /* defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) */405406#endif /* SDL_intrin_h_ */407408409