From e19b546b40a3a954f8dcf9c9e1dbb84b3f381deb Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 10 Oct 2018 19:30:32 +0100 Subject: [PATCH 08/11] ARM: Create configure option --enable-arm-neon to govern assembly optimizations --- configure.in | 39 +++++++++++++++++++++++++++++++++++++++ include/SDL_config.h.in | 1 + include/SDL_cpuinfo.h | 3 +++ src/cpuinfo/SDL_cpuinfo.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+) diff --git a/configure.in b/configure.in index 76a63108d..ff374c86a 100644 --- a/configure.in +++ b/configure.in @@ -922,6 +922,44 @@ dnl SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.c" fi } +dnl Check for ARM NEON instruction support using gas syntax +CheckNEON() +{ + AC_ARG_ENABLE(arm-neon, +AC_HELP_STRING([--enable-arm-neon], [use NEON assembly blitters on ARM [[default=yes]]]), + enable_arm_neon=$enableval, enable_arm_neon=yes) + if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_neon = xyes; then + save_CFLAGS="$CFLAGS" + have_arm_neon=no + CFLAGS="-x assembler-with-cpp $CFLAGS" + + AC_MSG_CHECKING(for ARM NEON) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + .text + .fpu neon + .arch armv7a + .object_arch armv4 + .eabi_attribute 10, 0 + .arm + .altmacro + #ifndef __ARM_EABI__ + #error EABI is required (to be sure that calling conventions are compatible) + #endif + pld [r0] + vmovn.u16 d0, q0 + ]])], have_arm_neon=yes) + AC_MSG_RESULT($have_arm_neon) + + CFLAGS="$save_CFLAGS" + + if test x$have_arm_neon = xyes; then + AC_DEFINE(SDL_ARM_NEON_BLITTERS) +dnl SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-neon*.c" + SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-neon*.S" + fi + fi +} + dnl See if GCC's -fvisibility=hidden is supported (gcc4 and later, usually). dnl Details of this flag are here: http://gcc.gnu.org/wiki/Visibility CheckVisibilityHidden() @@ -2466,6 +2504,7 @@ case "$host" in CheckNASM CheckAltivec CheckARM + CheckNEON CheckOSS CheckDMEDIA CheckMME diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index b319aaae9..9c5f45f8c 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -313,5 +313,6 @@ #undef SDL_HERMES_BLITTERS #undef SDL_ALTIVEC_BLITTERS #undef SDL_ARM_SIMD_BLITTERS +#undef SDL_ARM_NEON_BLITTERS #endif /* _SDL_config_h */ diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h index 9698e910d..1335b9823 100644 --- a/include/SDL_cpuinfo.h +++ b/include/SDL_cpuinfo.h @@ -63,6 +63,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void); /** This function returns true if the CPU has ARM SIMD (ARMv6) features */ extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void); +/** This function returns true if the CPU has ARM NEON features */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasARMNEON(void); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index b6d39a739..8c1027249 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -46,6 +46,7 @@ #define CPU_HAS_SSE2 0x00000080 #define CPU_HAS_ALTIVEC 0x00000100 #define CPU_HAS_ARM_SIMD 0x00000200 +#define CPU_HAS_ARM_NEON 0x00000400 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ /* This is the brute force way of detecting instruction sets... @@ -422,6 +423,25 @@ static __inline__ int CPU_haveARMSIMD(void) return arm_simd; } +static __inline__ int CPU_haveARMNEON(void) +{ + int arm_neon = 0; + int fd; + + fd = open("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + Elf32_auxv_t aux; + while (read(fd, &aux, sizeof aux) == sizeof aux) + { + if (aux.a_type == AT_HWCAP) + arm_neon = (aux.a_un.a_val & 4096) != 0; + } + close(fd); + } + return arm_neon; +} + #else static __inline__ int CPU_haveARMSIMD(void) @@ -429,6 +449,11 @@ static __inline__ int CPU_haveARMSIMD(void) return 0; } +static __inline__ int CPU_haveARMNEON(void) +{ + return 0; +} + #endif static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; @@ -464,6 +489,9 @@ static Uint32 SDL_GetCPUFeatures(void) if ( CPU_haveARMSIMD() ) { SDL_CPUFeatures |= CPU_HAS_ARM_SIMD; } + if ( CPU_haveARMNEON() ) { + SDL_CPUFeatures |= CPU_HAS_ARM_NEON; + } } return SDL_CPUFeatures; } @@ -540,6 +568,14 @@ SDL_bool SDL_HasARMSIMD(void) return SDL_FALSE; } +SDL_bool SDL_HasARMNEON(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_ARM_NEON ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + #ifdef TEST_MAIN #include @@ -555,6 +591,7 @@ int main() printf("SSE2: %d\n", SDL_HasSSE2()); printf("AltiVec: %d\n", SDL_HasAltiVec()); printf("ARM SIMD: %d\n", SDL_HasARMSIMD()); + printf("ARM NEON: %d\n", SDL_HasARMNEON()); return 0; } -- 2.11.0