From 6b4d06d5d1441ceeb1d233bd81a441155cc616e3 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 30 Jun 2010 17:14:54 -0700 Subject: [PATCH] neon: check for NEON support on CPU --- orc/orcarm.h | 2 ++ orc/orccpu-arm.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-- orc/orcprogram-neon.c | 9 ++++++++- orc/orcprogram.h | 3 ++- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/orc/orcarm.h b/orc/orcarm.h index 8e58f9a..6859558 100644 --- a/orc/orcarm.h +++ b/orc/orcarm.h @@ -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); diff --git a/orc/orccpu-arm.c b/orc/orccpu-arm.c index fb72086..c8de730 100644 --- a/orc/orccpu-arm.c +++ b/orc/orccpu-arm.c @@ -41,6 +41,9 @@ #include #include #include +#if defined(__linux__) +#include +#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 diff --git a/orc/orcprogram-neon.c b/orc/orcprogram-neon.c index 7dfb726..f27b034 100644 --- a/orc/orcprogram-neon.c +++ b/orc/orcprogram-neon.c @@ -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 diff --git a/orc/orcprogram.h b/orc/orcprogram.h index 4aa1611..6b919a9 100644 --- a/orc/orcprogram.h +++ b/orc/orcprogram.h @@ -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 { -- 2.7.4