From fac036df20c1efd009200eb7db7be1e895899a56 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Fri, 12 Aug 2016 18:07:30 +0100 Subject: [PATCH 01/11] ARM: Create configure option --enable-arm-simd to govern assembly optimizations --- configure.in | 37 +++++++++++++++++++++++++++ include/SDL_config.h.in | 1 + include/SDL_cpuinfo.h | 3 +++ src/cpuinfo/SDL_cpuinfo.c | 53 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/configure.in b/configure.in index 13516c2bc..76a63108d 100644 --- a/configure.in +++ b/configure.in @@ -886,6 +886,42 @@ AC_HELP_STRING([--enable-altivec], [use altivec assembly blitters on PPC [[defau fi } +dnl Check for ARM instruction support using gas syntax +CheckARM() +{ + AC_ARG_ENABLE(arm-simd, +AC_HELP_STRING([--enable-arm-simd], [use SIMD assembly blitters on ARM [[default=yes]]]), + enable_arm_simd=$enableval, enable_arm_simd=yes) + if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_simd = xyes; then + save_CFLAGS="$CFLAGS" + have_arm_simd=no + CFLAGS="-x assembler-with-cpp $CFLAGS" + + AC_MSG_CHECKING(for ARM SIMD) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + .text + .arch armv6 + .object_arch armv4 + .arm + .altmacro + #ifndef __ARM_EABI__ + #error EABI is required (to be sure that calling conventions are compatible) + #endif + pld [r0] + uqadd8 r0, r0, r0 + ]])], have_arm_simd=yes) + AC_MSG_RESULT($have_arm_simd) + + CFLAGS="$save_CFLAGS" + + if test x$have_arm_simd = xyes; then + AC_DEFINE(SDL_ARM_SIMD_BLITTERS) +dnl SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.c" + SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.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() @@ -2429,6 +2465,7 @@ case "$host" in CheckDLOPEN CheckNASM CheckAltivec + CheckARM CheckOSS CheckDMEDIA CheckMME diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index df4fa4dad..b319aaae9 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -312,5 +312,6 @@ #undef SDL_ASSEMBLY_ROUTINES #undef SDL_HERMES_BLITTERS #undef SDL_ALTIVEC_BLITTERS +#undef SDL_ARM_SIMD_BLITTERS #endif /* _SDL_config_h */ diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h index 4200d6d17..9698e910d 100644 --- a/include/SDL_cpuinfo.h +++ b/include/SDL_cpuinfo.h @@ -60,6 +60,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void); /** This function returns true if the CPU has AltiVec features */ 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); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 93f1a326d..b6d39a739 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -45,6 +45,7 @@ #define CPU_HAS_SSE 0x00000040 #define CPU_HAS_SSE2 0x00000080 #define CPU_HAS_ALTIVEC 0x00000100 +#define CPU_HAS_ARM_SIMD 0x00000200 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ /* This is the brute force way of detecting instruction sets... @@ -390,6 +391,46 @@ static __inline__ int CPU_haveAltiVec(void) return altivec; } +#ifdef __linux__ + +#include +#include +#include +#include +#include + +static __inline__ int CPU_haveARMSIMD(void) +{ + int arm_simd = 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_PLATFORM) + { + const char *plat = (const char *) aux.a_un.a_val; + arm_simd = strncmp(plat, "v6l", 3) == 0 || + strncmp(plat, "v7l", 3) == 0; + } + } + close(fd); + } + return arm_simd; +} + +#else + +static __inline__ int CPU_haveARMSIMD(void) +{ + return 0; +} + +#endif + static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; static Uint32 SDL_GetCPUFeatures(void) @@ -420,6 +461,9 @@ static Uint32 SDL_GetCPUFeatures(void) if ( CPU_haveAltiVec() ) { SDL_CPUFeatures |= CPU_HAS_ALTIVEC; } + if ( CPU_haveARMSIMD() ) { + SDL_CPUFeatures |= CPU_HAS_ARM_SIMD; + } } return SDL_CPUFeatures; } @@ -488,6 +532,14 @@ SDL_bool SDL_HasAltiVec(void) return SDL_FALSE; } +SDL_bool SDL_HasARMSIMD(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_ARM_SIMD ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + #ifdef TEST_MAIN #include @@ -502,6 +554,7 @@ int main() printf("SSE: %d\n", SDL_HasSSE()); printf("SSE2: %d\n", SDL_HasSSE2()); printf("AltiVec: %d\n", SDL_HasAltiVec()); + printf("ARM SIMD: %d\n", SDL_HasARMSIMD()); return 0; } -- 2.17.1