neon: check for NEON support on CPU
authorDavid Schleef <ds@schleef.org>
Thu, 1 Jul 2010 00:14:54 +0000 (17:14 -0700)
committerDavid Schleef <ds@schleef.org>
Thu, 1 Jul 2010 00:14:54 +0000 (17:14 -0700)
orc/orcarm.h
orc/orccpu-arm.c
orc/orcprogram-neon.c
orc/orcprogram.h

index 8e58f9a..6859558 100644 (file)
@@ -68,6 +68,8 @@ typedef enum {
   ORC_ARM_ROR
 } OrcArmShift;
 
+unsigned long orc_arm_get_cpu_flags (void);
+
 void orc_arm_emit (OrcCompiler *compiler, orc_uint32 insn);
 void orc_arm_emit_bx_lr (OrcCompiler *compiler);
 const char * orc_arm_reg_name (int reg);
index fb72086..c8de730 100644 (file)
@@ -41,6 +41,9 @@
 #include <signal.h>
 #include <sys/time.h>
 #include <time.h>
+#if defined(__linux__)
+#include <linux/auxvec.h>
+#endif
 
 /***** arm *****/
 
@@ -57,6 +60,44 @@ orc_profile_stamp_xscale(void)
 }
 #endif
 
+#if defined(__linux__)
+static unsigned long
+orc_check_neon_proc_auxv (void)
+{
+  unsigned long flags = 0;
+  unsigned long aux[2];
+  ssize_t count;
+  int fd;
+
+  fd = open("/proc/self/auxv", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+
+  while (1) {
+    count = read(fd, aux, sizeof(aux));
+    if (count < sizeof(aux)) {
+      break;
+    }
+
+    if (aux[0] == AT_HWCAP) {
+      //if (aux[1] & 64) flags |= ORC_TARGET_NEON_VFP;
+      //if (aux[1] & 512) flags |= ORC_TARGET_NEON_IWMMXT;
+      if (aux[1] & 4096) flags |= ORC_TARGET_NEON_NEON;
+      ORC_INFO("arm hwcap %08x", aux[1]);
+    } if (aux[0] == AT_PLATFORM) {
+      ORC_INFO("arm platform %s", (char *)aux[1]);
+    } else if (aux[0] == AT_NULL) {
+      break;
+    }
+  }
+
+  close(fd);
+
+  return flags;
+}
+#endif
+
 #ifdef unused
 static void
 orc_cpu_arm_getflags_cpuinfo (char *cpuinfo)
@@ -120,9 +161,14 @@ get_proc_cpuinfo (void)
 }
 #endif
 
-void
-orc_cpu_detect_arch(void)
+unsigned long
+orc_arm_get_cpu_flags (void)
 {
+  unsigned long neon_flags = 0;
+
+#ifdef __linux__
+  neon_flags = orc_check_neon_proc_auxv ();
+#endif
 #ifdef unused
 #ifdef __linux__
   int arm_implementer = 0;
@@ -163,6 +209,11 @@ orc_cpu_detect_arch(void)
   free (cpuinfo);
 #endif
 #endif
+  if (orc_compiler_flag_check ("-neon")) {
+    neon_flags &= ~ORC_TARGET_NEON_NEON;
+  }
+
+  return neon_flags;
 }
 #endif
 
index 7dfb726..f27b034 100644 (file)
@@ -102,6 +102,13 @@ static OrcTarget neon_target = {
 void
 orc_neon_init (void)
 {
+#if defined(HAVE_ARM)
+  if (!(orc_arm_get_cpu_flags () & ORC_TARGET_NEON_NEON)) {
+    ORC_INFO("marking neon backend non-executable");
+    neon_target.executable = FALSE;
+  }
+#endif
+
   orc_target_register (&neon_target);
 
   orc_compiler_neon_register_rules (&neon_target);
@@ -110,7 +117,7 @@ orc_neon_init (void)
 unsigned int
 orc_compiler_neon_get_default_flags (void)
 {
-  return 0;
+  return ORC_TARGET_NEON_NEON;
 }
 
 void
index 4aa1611..6b919a9 100644 (file)
@@ -84,7 +84,8 @@ enum {
 };
 
 enum {
-  ORC_TARGET_NEON_CLEAN_COMPILE = (1<<0)
+  ORC_TARGET_NEON_CLEAN_COMPILE = (1<<0),
+  ORC_TARGET_NEON_NEON = (1<<1)
 };
 
 typedef enum {