cpuinfo: more work on SDL_HasNEON().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c
index f98cf76..1253797 100644
--- a/src/cpuinfo/SDL_cpuinfo.c
+++ b/src/cpuinfo/SDL_cpuinfo.c
@@ -50,13 +50,7 @@
#include <setjmp.h>
#endif
-#if 0 /* !!! FIXME */
-#if defined(__ANDROID__) && defined(__ARM_ARCH)
-#include <cpu-features.h>
-#endif
-#endif
-
-#if defined(__LINUX__) && defined(__ARM_ARCH) && HAVE_GETAUXVAL
+#if defined(__LINUX__) && defined(__ARM_ARCH)
#include <sys/auxv.h>
#include <asm/hwcap.h>
#endif
@@ -300,38 +294,61 @@ CPU_haveAltiVec(void)
return altivec;
}
+#if (defined(__LINUX__) || defined(__ANDROID__)) && !HAVE_GETAUXVAL
static int
-CPU_haveNEON(void)
+readProcAuxvForNeon(void)
{
int neon = 0;
+ int kv[2];
+ const int fd = open("/proc/self/auxv", O_RDONLY);
+
+ if (fd == -1) {
+ return 0;
+ }
+
+ while (read(fd, kv, sizeof (kv)) == sizeof (kv)) {
+ if (kv[0] == AT_HWCAP) {
+ neon = ((kv[1] & HWCAP_NEON) == HWCAP_NEON);
+ break;
+ }
+ }
+
+ close(fd);
+
+ return neon;
+}
+#endif
+
+static int
+CPU_haveNEON(void)
+{
/* 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)
+#if defined(SDL_CPUINFO_DISABLED) || !defined(__ARM_ARCH)
+ return 0;
+#elif __ARM_ARCH >= 8
+ return 1; // ARMv8 always has non-optional NEON support.
+#elif defined(__APPLE__)
/* all hardware that runs iOS 5 and later support NEON, but check anyhow */
+ int neon = 0;
size_t length = sizeof (neon);
const int error = sysctlbyname("hw.optional.neon", &neon, &length, NULL, 0);
- if (!error)
- neon = (neon != 0);
-#elif 0 && defined(__ANDROID__) && defined(__ARM_ARCH) /* !!! FIXME */
- if ( (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) &&
- ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0) ) {
- neon = 1;
- }
-#elif defined(__LINUX__) && defined(__ARM_ARCH) && HAVE_GETAUXVAL
- if (getauxval(AT_HWCAP) & HWCAP_NEON) {
- neon = 1;
- }
+ return (!error) && (neon != 0);
+/* Android offers a static library for this but all it does is parse /proc/cpuinfo */
+#elif (defined(__LINUX__) || defined(__ANDROID__)) && HAVE_GETAUXVAL
+ return ((getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON)
+#elif (defined(__LINUX__) || defined(__ANDROID__))
+ return readProcAuxvForNeon();
#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;
}
+#else
+#warning SDL_HasNEON is not implemented for this ARM platform. Write me.
#endif
#endif
-
- return neon;
}
static int