diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-06-27 22:05:18 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-07-07 01:09:23 -0400 |
commit | 4b78d785373c1d02abe695267379674776b3da3d (patch) | |
tree | 29e5c8727f9d93b41d8ed8a3209d3e8672b65c23 | |
parent | 8b795a9c17aa25328b9c76b949d319bb578d5f1e (diff) |
Simplifications to ARM CPU detection
Organize pixman-arm.c such that each operating system/compiler exports
a detect_cpu_features() function that returns a bitmask with the
various features that we are interested in. A new function
have_feature() then calls this function, caches the result, and return
whether the given feature is available.
The result is that all the pixman_have_arm_<feature> functions become
redundant and can be deleted.
-rw-r--r-- | pixman/pixman-arm.c | 244 |
1 files changed, 87 insertions, 157 deletions
diff --git a/pixman/pixman-arm.c b/pixman/pixman-arm.c index 6625d7ff..23374e41 100644 --- a/pixman/pixman-arm.c +++ b/pixman/pixman-arm.c @@ -25,132 +25,83 @@ #include "pixman-private.h" +typedef enum +{ + ARM_V7 = (1 << 0), + ARM_V6 = (1 << 1), + ARM_VFP = (1 << 2), + ARM_NEON = (1 << 3), + ARM_IWMMXT = (1 << 4) +} arm_cpu_features_t; + #if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) -#include <string.h> -#include <stdlib.h> +#if defined(_MSC_VER) -#if defined(USE_ARM_SIMD) && defined(_MSC_VER) /* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ #include <windows.h> -#endif -#if defined(__APPLE__) -#include "TargetConditionals.h" -#endif - -#if defined(_MSC_VER) - -#if defined(USE_ARM_SIMD) +extern int pixman_msvc_try_arm_neon_op (); extern int pixman_msvc_try_arm_simd_op (); -pixman_bool_t -pixman_have_arm_simd (void) +static arm_cpu_features_t +detect_cpu_features (void) { - static pixman_bool_t initialized = FALSE; - static pixman_bool_t have_arm_simd = FALSE; + arm_cpu_features_t features = 0; - if (!initialized) + __try + { + pixman_msvc_try_arm_simd_op (); + features |= ARM_V6; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { - __try { - pixman_msvc_try_arm_simd_op (); - have_arm_simd = TRUE; - } __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { - have_arm_simd = FALSE; - } - initialized = TRUE; } - return have_arm_simd; -} - -#endif /* USE_ARM_SIMD */ - -#if defined(USE_ARM_NEON) -extern int pixman_msvc_try_arm_neon_op (); - -pixman_bool_t -pixman_have_arm_neon (void) -{ - static pixman_bool_t initialized = FALSE; - static pixman_bool_t have_arm_neon = FALSE; - - if (!initialized) + __try + { + pixman_msvc_try_arm_neon_op (); + features |= ARM_NEON; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) { - __try - { - pixman_msvc_try_arm_neon_op (); - have_arm_neon = TRUE; - } - __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) - { - have_arm_neon = FALSE; - } - initialized = TRUE; } - return have_arm_neon; + return features; } -#endif /* USE_ARM_NEON */ - -#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */ - -/* Detection of ARM NEON on iOS is fairly simple because iOS binaries - * contain separate executable images for each processor architecture. - * So all we have to do is detect the armv7 architecture build. The - * operating system automatically runs the armv7 binary for armv7 devices - * and the armv6 binary for armv6 devices. - */ +#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */ -pixman_bool_t -pixman_have_arm_simd (void) -{ -#if defined(USE_ARM_SIMD) - return TRUE; -#else - return FALSE; -#endif -} +#include "TargetConditionals.h" -pixman_bool_t -pixman_have_arm_neon (void) +static arm_cpu_features_t +detect_cpu_features (void) { -#if defined(USE_ARM_NEON) && defined(__ARM_NEON__) - /* This is an armv7 cpu build */ - return TRUE; -#else - /* This is an armv6 cpu build */ - return FALSE; + arm_cpu_features_t features = 0; + + features |= ARM_V6; + + /* Detection of ARM NEON on iOS is fairly simple because iOS binaries + * contain separate executable images for each processor architecture. + * So all we have to do is detect the armv7 architecture build. The + * operating system automatically runs the armv7 binary for armv7 devices + * and the armv6 binary for armv6 devices. + */ +#if defined(__ARM_NEON__) + features |= ARM_NEON; #endif -} -pixman_bool_t -pixman_have_arm_iwmmxt (void) -{ -#if defined(USE_ARM_IWMMXT) - return FALSE; -#else - return FALSE; -#endif + return features; } -#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */ - -static pixman_bool_t arm_has_v7 = FALSE; -static pixman_bool_t arm_has_v6 = FALSE; -static pixman_bool_t arm_has_vfp = FALSE; -static pixman_bool_t arm_has_neon = FALSE; -static pixman_bool_t arm_has_iwmmxt = FALSE; -static pixman_bool_t arm_tests_initialized = FALSE; - -#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */ +#elif defined(__ANDROID__) || defined(ANDROID) /* Android */ #include <cpu-features.h> -static void -pixman_arm_read_auxv_or_cpu_features () +static arm_cpu_features_t +detect_cpu_features (void) { + arm_cpu_features_t features = 0; AndroidCpuFamily cpu_family; uint64_t cpu_features; @@ -160,16 +111,16 @@ pixman_arm_read_auxv_or_cpu_features () if (cpu_family == ANDROID_CPU_FAMILY_ARM) { if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7) - arm_has_v7 = TRUE; - + features |= ARM_V7; + if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3) - arm_has_vfp = TRUE; - + features |= ARM_VFP; + if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) - arm_has_neon = TRUE; + features |= ARM_NEON; } - arm_tests_initialized = TRUE; + return features; } #elif defined (__linux__) /* linux ELF */ @@ -182,11 +133,12 @@ pixman_arm_read_auxv_or_cpu_features () #include <string.h> #include <elf.h> -static void -pixman_arm_read_auxv_or_cpu_features () +static arm_cpu_features_t +detect_cpu_features (void) { - int fd; + arm_cpu_features_t features = 0; Elf32_auxv_t aux; + int fd; fd = open ("/proc/self/auxv", O_RDONLY); if (fd >= 0) @@ -196,100 +148,78 @@ pixman_arm_read_auxv_or_cpu_features () if (aux.a_type == AT_HWCAP) { uint32_t hwcap = aux.a_un.a_val; + /* hardcode these values to avoid depending on specific * versions of the hwcap header, e.g. HWCAP_NEON */ - arm_has_vfp = (hwcap & 64) != 0; - arm_has_iwmmxt = (hwcap & 512) != 0; + if ((hwcap & 64) != 0) + features |= ARM_VFP; + if ((hwcap & 512) != 0) + features |= ARM_IWMMXT; /* this flag is only present on kernel 2.6.29 */ - arm_has_neon = (hwcap & 4096) != 0; + if ((hwcap & 4096) != 0) + features |= ARM_NEON; } else if (aux.a_type == AT_PLATFORM) { const char *plat = (const char*) aux.a_un.a_val; + if (strncmp (plat, "v7l", 3) == 0) - { - arm_has_v7 = TRUE; - arm_has_v6 = TRUE; - } + features |= (ARM_V7 | ARM_V6); else if (strncmp (plat, "v6l", 3) == 0) - { - arm_has_v6 = TRUE; - } + features |= ARM_V6; } } close (fd); } - arm_tests_initialized = TRUE; + return features; } -#endif /* Linux elf */ +#else /* Unknown */ -#if defined(USE_ARM_SIMD) -pixman_bool_t -pixman_have_arm_simd (void) +static arm_cpu_features_t +detect_cpu_features (void) { - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); - - return arm_has_v6; + return 0; } -#endif /* USE_ARM_SIMD */ +#endif /* Linux elf */ -#if defined(USE_ARM_NEON) -pixman_bool_t -pixman_have_arm_neon (void) +static pixman_bool_t +have_feature (arm_cpu_features_t feature) { - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); - - return arm_has_neon; -} + static pixman_bool_t initialized; + static arm_cpu_features_t features; -#endif /* USE_ARM_NEON */ - -#if defined(USE_ARM_IWMMXT) -pixman_bool_t -pixman_have_arm_iwmmxt (void) -{ - if (!arm_tests_initialized) - pixman_arm_read_auxv_or_cpu_features (); + if (!initialized) + { + features = detect_cpu_features(); + initialized = TRUE; + } - return arm_has_iwmmxt; + return (features & feature) == feature; } -#endif /* USE_ARM_IWMMXT */ - -#else /* !_MSC_VER && !Linux elf && !Android */ - -#define pixman_have_arm_simd() FALSE -#define pixman_have_arm_neon() FALSE -#define pixman_have_arm_iwmmxt() FALSE - -#endif - #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ pixman_implementation_t * _pixman_arm_get_implementations (pixman_implementation_t *imp) { #ifdef USE_ARM_SIMD - if (!_pixman_disabled ("arm-simd") && pixman_have_arm_simd ()) + if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6)) imp = _pixman_implementation_create_arm_simd (imp); #endif #ifdef USE_ARM_IWMMXT - if (!_pixman_disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) + if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT)) imp = _pixman_implementation_create_mmx (imp); #endif #ifdef USE_ARM_NEON - if (!_pixman_disabled ("arm-neon") && pixman_have_arm_neon ()) + if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON)) imp = _pixman_implementation_create_arm_neon (imp); #endif return imp; } - |