From 34f552fae991a08065d4d5a2aff7a1bf3b3d0506 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 26 Nov 2018 18:16:34 +0100 Subject: [PATCH] add universal executable to select binary based on current ISA - using cpuid to check x86 features - using hwcap on ARM to check for NEON --- CMakeLists.txt | 3 +- lib/src/common/CMakeLists.txt | 2 + lib/src/common/arch_select.cc | 104 ++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 lib/src/common/arch_select.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0f05568..f70f6d569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,7 +317,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=native -DIS_ARM -DHAVE_NEON") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=native -DIS_ARM -DHAVE_NEON") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIS_ARM") message(STATUS "have ARM") set(HAVE_NEON "True") else(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 010f8f730..5e5bda2b0 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -25,6 +25,8 @@ add_library(srslte_common STATIC ${C_SOURCES} ${CXX_SOURCES}) add_custom_target(gen_build_info COMMAND cmake -P ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake) add_dependencies(srslte_common gen_build_info) +add_executable(arch_select arch_select.cc) + target_include_directories(srslte_common PUBLIC ${SEC_INCLUDE_DIRS}) target_link_libraries(srslte_common ${SEC_LIBRARIES}) install(TARGETS srslte_common DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/common/arch_select.cc b/lib/src/common/arch_select.cc new file mode 100644 index 000000000..947b6501e --- /dev/null +++ b/lib/src/common/arch_select.cc @@ -0,0 +1,104 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include +#include + +#ifdef IS_ARM +#include +#include +#include +#else +#include +#define X86_CPUID_BASIC_LEAF 1 +#define X86_CPUID_ADVANCED_LEAF 7 +#endif + +#define MAX_CMD_LEN (64) + +#ifndef IS_ARM +const char* x86_get_isa() +{ + int ret = 0; + int has_sse42 = 0, has_avx = 0, has_avx2 = 0; + unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; + + // query basic features + ret = __get_cpuid(X86_CPUID_BASIC_LEAF, &eax, &ebx, &ecx, &edx); + if (ret) { + has_sse42 = ecx & bit_SSE4_2; + has_avx = ecx & bit_AVX; + } + + // query advanced features + ret = __get_cpuid_count(X86_CPUID_ADVANCED_LEAF, 0, &eax, &ebx, &ecx, &edx); + if (ret) { + has_avx2 = ebx & bit_AVX2; + } + + if (has_avx2) { + return "avx2"; + } else + if (has_avx) { + return "avx"; + } else + if (has_sse42) { + return "sse4.2"; + } else { + return "generic"; + } +} +#endif + +#ifdef IS_ARM +const char* arm_get_isa() +{ + if (getauxval(AT_HWCAP) & HWCAP_NEON) { + return "neon"; + } else { + return "generic"; + } +} +#endif + +int main(int argc, char *argv[]) +{ + char cmd[MAX_CMD_LEN]; +#ifdef IS_ARM + snprintf(cmd, MAX_CMD_LEN, "%s-%s", argv[0], arm_get_isa()); +#else + snprintf(cmd, MAX_CMD_LEN, "%s-%s", argv[0], x86_get_isa()); +#endif + + // execute command with same argument + if (execvp(cmd, &argv[0]) == -1) { + fprintf(stderr, "%s: %s\n", cmd, strerror(errno)); + exit(errno); + } +} \ No newline at end of file