Skip to content

Commit

Permalink
cpuinfo: first attempt at SDL_HasNEON() implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Nov 17, 2016
1 parent 7592b40 commit 35430a7
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -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}")
Expand Down
2 changes: 1 addition & 1 deletion configure.in
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions include/SDL_config.h.cmake
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions include/SDL_config.h.in
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions include/SDL_cpuinfo.h
Expand Up @@ -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.
*/
Expand Down
54 changes: 54 additions & 0 deletions src/cpuinfo/SDL_cpuinfo.c
Expand Up @@ -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
Expand All @@ -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...
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Expand Up @@ -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)
1 change: 1 addition & 0 deletions test/testplatform.c
Expand Up @@ -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);
Expand Down

0 comments on commit 35430a7

Please sign in to comment.