cpuinfo: first attempt at SDL_HasNEON() implementation.

Ryan C. Gordon 2016-11-17 01:15:16 -05:00
parent 7592b40b39
commit 35430a73f2
9 changed files with 67 additions and 2 deletions

View File

@ -615,7 +615,7 @@ if(LIBC)
_uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull
atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp
vsscanf vsnprintf fseeko fseeko64 sigaction setjmp
nanosleep sysconf sysctlbyname
nanosleep sysconf sysctlbyname getauxval
)
string(TOUPPER ${_FN} _UPPER)
set(_HAVEVAR "HAVE_${_UPPER}")

View File

@ -268,7 +268,7 @@ if test x$enable_libc = xyes; then
AC_DEFINE(HAVE_MPROTECT, 1, [ ])
]),
)
AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname)
AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval)
AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
AC_CHECK_FUNCS(atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt sqrtf tan tanf)

View File

@ -171,6 +171,8 @@
#cmakedefine HAVE_PTHREAD_SETNAME_NP 1
#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1
#cmakedefine HAVE_SEM_TIMEDWAIT 1
#cmakedefine HAVE_GETAUXVAL 1
#elif __WIN32__
#cmakedefine HAVE_STDARG_H 1
#cmakedefine HAVE_STDDEF_H 1

View File

@ -173,6 +173,7 @@
#undef HAVE_PTHREAD_SETNAME_NP
#undef HAVE_PTHREAD_SET_NAME_NP
#undef HAVE_SEM_TIMEDWAIT
#undef HAVE_GETAUXVAL
#else
#define HAVE_STDARG_H 1

View File

@ -144,6 +144,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
*/
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
/**
* This function returns true if the CPU has NEON (ARM SIMD) features.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
/**
* This function returns the amount of RAM configured in the system, in MB.
*/

View File

@ -50,6 +50,15 @@
#include <setjmp.h>
#endif
#if defined(__ANDROID__)
#include <cpu-features.h>
#endif
#if defined(__LINUX__) && HAVE_GETAUXVAL
#include <sys/auxv.h>
#include <asm/hwcap.h>
#endif
#define CPU_HAS_RDTSC 0x00000001
#define CPU_HAS_ALTIVEC 0x00000002
#define CPU_HAS_MMX 0x00000004
@ -61,6 +70,7 @@
#define CPU_HAS_SSE42 0x00000200
#define CPU_HAS_AVX 0x00000400
#define CPU_HAS_AVX2 0x00000800
#define CPU_HAS_NEON 0x00001000
#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
/* This is the brute force way of detecting instruction sets...
@ -288,6 +298,40 @@ CPU_haveAltiVec(void)
return altivec;
}
static int
CPU_haveNEON(void)
{
int neon = 0;
/* The way you detect NEON is a privileged instruction on ARM, so you have
query the OS kernel in a platform-specific way. :/ */
#ifndef SDL_CPUINFO_DISABLED
#if defined(__APPLE__) && defined(__ARM_ARCH)
/* all hardware that runs iOS 5 and later support NEON, but check anyhow */
size_t length = sizeof (neon);
const int error = sysctlbyname("hw.optional.neon", &neon, &length, NULL, 0);
if (!error)
neon = (neon != 0);
#elif defined(__ANDROID__)
if ( (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0) ) {
neon = 1;
}
#elif defined(__LINUX__) && HAVE_GETAUXVAL && defined(__arm__)
if (getauxval(AT_HWCAP) & HWCAP_NEON) {
neon = 1;
}
#elif (defined(__WINDOWS__) || defined(__WINRT__)) && defined(_M_ARM)
/* All WinRT ARM devices are required to support NEON, but just in case. */
if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) {
neon = 1;
}
#endif
#endif
return neon;
}
static int
CPU_have3DNow(void)
{
@ -527,6 +571,9 @@ SDL_GetCPUFeatures(void)
if (CPU_haveAVX2()) {
SDL_CPUFeatures |= CPU_HAS_AVX2;
}
if (CPU_haveNEON()) {
SDL_CPUFeatures |= CPU_HAS_NEON;
}
}
return SDL_CPUFeatures;
}
@ -598,6 +645,12 @@ SDL_HasAVX2(void)
return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX2);
}
SDL_bool
SDL_HasNEON(void)
{
return CPU_FEATURE_AVAILABLE(CPU_HAS_NEON);
}
static int SDL_SystemRAM = 0;
int
@ -667,6 +720,7 @@ main()
printf("SSE4.2: %d\n", SDL_HasSSE42());
printf("AVX: %d\n", SDL_HasAVX());
printf("AVX2: %d\n", SDL_HasAVX2());
printf("NEON: %d\n", SDL_HasNEON());
printf("RAM: %d MB\n", SDL_GetSystemRAM());
return 0;
}

View File

@ -621,3 +621,4 @@
#define SDL_GameControllerGetVendor SDL_GameControllerGetVendor_REAL
#define SDL_GameControllerGetProduct SDL_GameControllerGetProduct_REAL
#define SDL_GameControllerGetProductVersion SDL_GameControllerGetProductVersion_REAL
#define SDL_HasNEON SDL_HasNEON_REAL

View File

@ -653,3 +653,4 @@ SDL_DYNAPI_PROC(Uint16,SDL_JoystickGetProductVersion,(SDL_Joystick *a),(a),retur
SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetVendor,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetProduct,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetProductVersion,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasNEON,(void),(),return)

View File

@ -360,6 +360,7 @@ TestCPUInfo(SDL_bool verbose)
SDL_Log("SSE4.2 %s\n", SDL_HasSSE42()? "detected" : "not detected");
SDL_Log("AVX %s\n", SDL_HasAVX()? "detected" : "not detected");
SDL_Log("AVX2 %s\n", SDL_HasAVX2()? "detected" : "not detected");
SDL_Log("NEON %s\n", SDL_HasNEON()? "detected" : "not detected");
SDL_Log("System RAM %d MB\n", SDL_GetSystemRAM());
}
return (0);