summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2013-08-27 13:03:12 -0400
committerTom Rondeau <tom@trondeau.com>2013-08-27 13:03:12 -0400
commit584f201d23e266400111dd24657b7f63868941b8 (patch)
treeb1a124fde7f271107c2f57bd030e685d49a04a9c
parentf8a150552f0659f07f2066241ced769cb279bdc5 (diff)
parent48fe4d89f22e8e9db7d01830e57e6868cfdaf4e4 (diff)
Merge branch 'maint'
-rw-r--r--volk/lib/CMakeLists.txt31
-rw-r--r--volk/tmpl/volk_cpu.tmpl.c2
2 files changed, 31 insertions, 2 deletions
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt
index 68fadc35b0..d2b3cb5a90 100644
--- a/volk/lib/CMakeLists.txt
+++ b/volk/lib/CMakeLists.txt
@@ -119,14 +119,43 @@ endmacro(OVERRULE_ARCH)
########################################################################
# eliminate AVX on GCC < 4.4
-# even though it accepts -mavx, as won't assemble xgetbv, which we need
+# even though it accepts -mavx, as won't assemble xgetbv, which we need.
+# even on GCC >= 4.4, verify that the compiler/linked accepts the xgetbv instruction,
+# and if not cross-compiling verify that the executable runs cleanly.
########################################################################
if(CPU_IS_x86 AND COMPILER_NAME MATCHES "GNU")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
if(GCC_VERSION VERSION_LESS "4.4")
OVERRULE_ARCH(avx "GCC missing xgetbv")
+ else()
+ # check to make sure compiler/linker works with xgetb instruction
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "unsigned long long _xgetbv(unsigned int index) { unsigned int eax, edx; __asm__ __volatile__(\"xgetbv\" : \"=a\"(eax), \"=d\"(edx) : \"c\"(index)); return ((unsigned long long)edx << 32) | eax; } int main (void) { (void) _xgetbv(0); return (0); }")
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -o
+ ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv
+ ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c
+ OUTPUT_QUIET ERROR_QUIET
+ RESULT_VARIABLE avx_compile_result)
+ if(NOT ${avx_compile_result} EQUAL 0)
+ OVERRULE_ARCH(avx "Compiler or linker missing xgetbv instruction")
+ elseif(NOT CROSSCOMPILE_MULTILIB)
+ execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv
+ OUTPUT_QUIET ERROR_QUIET
+ RESULT_VARIABLE avx_exe_result)
+ if(NOT ${avx_exe_result} EQUAL 0)
+ OVERRULE_ARCH(avx "CPU missing xgetbv.")
+ else()
+ add_definitions(-DHAVE_XGETBV)
+ endif()
+ else()
+ # cross compiling and compiler/linker seems to work; assume working
+ add_definitions(-DHAVE_XGETBV)
+ endif()
+ file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv
+ ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c)
endif()
+else()
+ OVERRULE_ARCH(avx "Not using GCC; assuming no xgetbv")
endif()
########################################################################
diff --git a/volk/tmpl/volk_cpu.tmpl.c b/volk/tmpl/volk_cpu.tmpl.c
index b1a0a4afe1..71f42f220d 100644
--- a/volk/tmpl/volk_cpu.tmpl.c
+++ b/volk/tmpl/volk_cpu.tmpl.c
@@ -44,7 +44,7 @@ struct VOLK_CPU volk_cpu;
* This function will bomb on non-AVX-capable machines, so
* check for AVX capability before executing.
*/
- #if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4
+ #if (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4) && defined(HAVE_XGETBV)
static inline unsigned long long _xgetbv(unsigned int index){
unsigned int eax, edx;
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));