volk (2.4.0-3) unstable; urgency=medium
authorA. Maitland Bottoms <bottoms@debian.org>
Fri, 4 Dec 2020 01:43:29 +0000 (01:43 +0000)
committerA. Maitland Bottoms <bottoms@debian.org>
Fri, 4 Dec 2020 01:43:29 +0000 (01:43 +0000)
  * Fix binary-indep build (Closes: #976300)
  * Upload to unstable

[dgit import unpatched volk 2.4.0-3]

81 files changed:
1  2  3 
cpu-features/.clang-format
cpu-features/.github/workflows/Dockerfile
cpu-features/.github/workflows/clang_format.yml
cpu-features/.gitignore
cpu-features/.travis.yml
cpu-features/CMakeLists.txt
cpu-features/CONTRIBUTING.md
cpu-features/LICENSE
cpu-features/README.md
cpu-features/WORKSPACE
cpu-features/appveyor.yml
cpu-features/cmake/CpuFeaturesConfig.cmake.in
cpu-features/cmake/CpuFeaturesNdkCompatConfig.cmake.in
cpu-features/cmake/README.md
cpu-features/cmake/googletest.CMakeLists.txt.in
cpu-features/include/cpu_features_cache_info.h
cpu-features/include/cpu_features_macros.h
cpu-features/include/cpuinfo_aarch64.h
cpu-features/include/cpuinfo_arm.h
cpu-features/include/cpuinfo_mips.h
cpu-features/include/cpuinfo_ppc.h
cpu-features/include/cpuinfo_x86.h
cpu-features/include/internal/bit_utils.h
cpu-features/include/internal/cpuid_x86.h
cpu-features/include/internal/filesystem.h
cpu-features/include/internal/hwcaps.h
cpu-features/include/internal/stack_line_reader.h
cpu-features/include/internal/string_view.h
cpu-features/ndk_compat/CMakeLists.txt
cpu-features/ndk_compat/README.md
cpu-features/ndk_compat/cpu-features.c
cpu-features/ndk_compat/cpu-features.h
cpu-features/ndk_compat/ndk-compat-test.c
cpu-features/scripts/run_integration.sh
cpu-features/scripts/test_integration.sh
cpu-features/src/cpuinfo_aarch64.c
cpu-features/src/cpuinfo_arm.c
cpu-features/src/cpuinfo_mips.c
cpu-features/src/cpuinfo_ppc.c
cpu-features/src/cpuinfo_x86.c
cpu-features/src/define_tables.h
cpu-features/src/filesystem.c
cpu-features/src/hwcaps.c
cpu-features/src/stack_line_reader.c
cpu-features/src/string_view.c
cpu-features/src/utils/list_cpu_features.c
cpu-features/test/CMakeLists.txt
cpu-features/test/bit_utils_test.cc
cpu-features/test/cpuinfo_aarch64_test.cc
cpu-features/test/cpuinfo_arm_test.cc
cpu-features/test/cpuinfo_mips_test.cc
cpu-features/test/cpuinfo_ppc_test.cc
cpu-features/test/cpuinfo_x86_test.cc
cpu-features/test/filesystem_for_testing.cc
cpu-features/test/filesystem_for_testing.h
cpu-features/test/hwcaps_for_testing.cc
cpu-features/test/hwcaps_for_testing.h
cpu-features/test/stack_line_reader_test.cc
cpu-features/test/string_view_test.cc
debian/changelog
debian/control
debian/copyright
debian/libvolk2-bin.install
debian/libvolk2-bin.manpages
debian/libvolk2-dev.acc
debian/libvolk2-dev.install
debian/libvolk2-doc.doc-base
debian/libvolk2-doc.docs
debian/libvolk2.4.install
debian/not-installed
debian/patches/cpu_features-CMake-option
debian/patches/make-acc-happy
debian/patches/optional-static-apps
debian/patches/remove-external-HTML-resources
debian/patches/series
debian/rules
debian/source/format
debian/volk-config-info.1
debian/volk_modtool.1
debian/volk_profile.1
debian/watch

index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..06ea346a1067b3be65359323067de98211a27851
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,4 @@@@
+++---
+++Language:        Cpp
+++BasedOnStyle:  Google
+++...
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..41dfc9378806ecb975d4a926b0dfe6c1575c2063
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,5 @@@@
+++# Create a virtual environment with all tools installed
+++# ref: https://hub.docker.com/_/alpine
+++FROM alpine:edge
+++# Install system build dependencies
+++RUN apk add --no-cache git clang
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..17d1567b5a7fdb08d558d1641407f6f134fe6d17
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,24 @@@@
+++name: clang-format Check
+++
+++on: [push, pull_request]
+++
+++jobs:
+++  # Building using the github runner environement directly.
+++  clang-format:
+++    runs-on: ubuntu-latest
+++    steps:
+++    - uses: actions/checkout@v2
+++    - name: Fetch origin/master
+++      run: git fetch origin master
+++    - name: List of changed file(s)
+++      run: git diff --name-only FETCH_HEAD
+++
+++    - name: Build clang-format docker
+++      run: cd .github/workflows && docker build --tag=linter .
+++    - name: Check clang-format
+++      run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --version
+++    - name: clang-format help
+++      run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --help
+++
+++    - name: Check current commit
+++      run: docker run --rm --init -v $(pwd):/repo -w /repo linter:latest sh -c "git diff --diff-filter=d --name-only FETCH_HEAD | grep '\.c$\|\.h$\|\.cc$' | xargs clang-format --style=file --dry-run --Werror "
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..628542461abbeeb7b65c98f6c00fd931888bec29
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,4 @@@@
+++cmake_build/
+++build/
+++
+++*.swp
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b5845be93dc34744a8b605141a66580e98296970
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,121 @@@@
+++language: c
+++
+++sudo: false
+++
+++cache:
+++  timeout: 1000
+++  directories:
+++    - $HOME/cpu_features_archives
+++
+++addons:
+++  apt_packages:
+++    - ninja-build
+++
+++env:
+++  global:
+++    TOOLCHAIN=NATIVE
+++    CMAKE_GENERATOR=Ninja
+++
+++matrix:
+++  include:
+++  - os: linux
+++    compiler: gcc
+++    env:
+++      TARGET=x86_64-linux-gnu
+++  - os: linux
+++    compiler: clang
+++    env:
+++      TARGET=x86_64-linux-gnu
+++  - os: osx
+++    compiler: gcc
+++    env:
+++      TARGET=x86_64-osx
+++      CMAKE_GENERATOR="Unix Makefiles"
+++  - os: osx
+++    compiler: clang
+++    env:
+++      TARGET=x86_64-osx
+++      CMAKE_GENERATOR="Unix Makefiles"
+++  - os: windows
+++    env:
+++      TARGET=x86_64-windows
+++      CMAKE_GENERATOR="Visual Studio 15 2017 Win64"
+++
+++  # see: https://docs.travis-ci.com/user/multi-cpu-architectures/
+++  - os: linux
+++    arch: ppc64le
+++    compiler: gcc
+++    env:
+++      TARGET=ppc64le-linux-gnu
+++  - os: linux
+++    arch: ppc64le
+++    compiler: clang
+++    env:
+++      TARGET=ppc64le-linux-gnu
+++
+++  # Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=aarch64-linux-gnu
+++      QEMU_ARCH=aarch64
+++  # Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=arm-linux-gnueabihf
+++      QEMU_ARCH=arm
+++  # Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=armv8l-linux-gnueabihf
+++      QEMU_ARCH=arm
+++  # Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=arm-linux-gnueabi
+++      QEMU_ARCH=arm
+++  # Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=aarch64_be-linux-gnu
+++      QEMU_ARCH=DISABLED
+++  # Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=armeb-linux-gnueabihf
+++      QEMU_ARCH=DISABLED
+++  # Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++  - os: linux
+++    env:
+++      TOOLCHAIN=LINARO
+++      TARGET=armeb-linux-gnueabi
+++      QEMU_ARCH=DISABLED
+++  - os: linux
+++    env:
+++      TOOLCHAIN=CODESCAPE
+++      TARGET=mips32
+++      QEMU_ARCH=mips
+++  - os: linux
+++    env:
+++      TOOLCHAIN=CODESCAPE
+++      TARGET=mips32el
+++      QEMU_ARCH=mipsel
+++  - os: linux
+++    env:
+++      TOOLCHAIN=CODESCAPE
+++      TARGET=mips64
+++      QEMU_ARCH=mips64
+++  - os: linux
+++    env:
+++      TOOLCHAIN=CODESCAPE
+++      TARGET=mips64el
+++      QEMU_ARCH=mips64el
+++
+++script:
+++  - cmake --version
+++  - bash -e -x ./scripts/run_integration.sh
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f9daeac52fe0ca4c81aea3e4d4575035d3ad92e5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,259 @@@@
+++cmake_minimum_required(VERSION 3.0)
+++
+++# option() honors normal variables.
+++# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
+++if(POLICY CMP0077)
+++  cmake_policy(SET CMP0077 NEW)
+++endif()
+++
+++project(CpuFeatures VERSION 0.6.0 LANGUAGES C)
+++
+++set(CMAKE_C_STANDARD 99)
+++
+++# Default Build Type to be Release
+++if(NOT CMAKE_BUILD_TYPE)
+++  set(CMAKE_BUILD_TYPE "Release" CACHE STRING
+++      "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
+++      FORCE)
+++endif(NOT CMAKE_BUILD_TYPE)
+++
+++# BUILD_TESTING is a standard CMake variable, but we declare it here to make it
+++# prominent in the GUI.
+++option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
+++# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
+++# it prominent in the GUI.
+++# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
+++# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
+++# Prefer static linking from source whenever possible.
+++option(BUILD_SHARED_LIBS "Build library as shared." OFF)
+++# PIC
+++option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC
+++
+++# Force PIC on unix when building shared libs
+++# see: https://en.wikipedia.org/wiki/Position-independent_code
+++if(BUILD_SHARED_LIBS AND UNIX)
+++  set(BUILD_PIC ON)
+++endif()
+++
+++include(CheckIncludeFile)
+++include(CheckSymbolExists)
+++include(GNUInstallDirs)
+++
+++macro(setup_include_and_definitions TARGET_NAME)
+++  target_include_directories(${TARGET_NAME}
+++    PUBLIC  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+++    PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/internal>
+++  )
+++  target_compile_definitions(${TARGET_NAME}
+++    PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024
+++  )
+++endmacro()
+++
+++set(PROCESSOR_IS_MIPS FALSE)
+++set(PROCESSOR_IS_ARM FALSE)
+++set(PROCESSOR_IS_AARCH64 FALSE)
+++set(PROCESSOR_IS_X86 FALSE)
+++set(PROCESSOR_IS_POWER FALSE)
+++
+++if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
+++  set(PROCESSOR_IS_MIPS TRUE)
+++elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
+++  set(PROCESSOR_IS_ARM TRUE)
+++elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
+++  set(PROCESSOR_IS_AARCH64 TRUE)
+++elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
+++  set(PROCESSOR_IS_X86 TRUE)
+++elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
+++  set(PROCESSOR_IS_POWER TRUE)
+++endif()
+++
+++macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
+++  list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h)
+++  list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h)
+++  if(PROCESSOR_IS_MIPS)
+++      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_mips.c)
+++  elseif(PROCESSOR_IS_ARM)
+++      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_arm.c)
+++  elseif(PROCESSOR_IS_AARCH64)
+++      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_aarch64.c)
+++  elseif(PROCESSOR_IS_X86)
+++      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_x86.c)
+++  elseif(PROCESSOR_IS_POWER)
+++      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
+++      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_ppc.c)
+++  else()
+++    message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
+++  endif()
+++endmacro()
+++
+++#
+++# library : utils
+++#
+++
+++add_library(utils OBJECT
+++  ${PROJECT_SOURCE_DIR}/include/internal/bit_utils.h
+++  ${PROJECT_SOURCE_DIR}/include/internal/filesystem.h
+++  ${PROJECT_SOURCE_DIR}/include/internal/stack_line_reader.h
+++  ${PROJECT_SOURCE_DIR}/include/internal/string_view.h
+++  ${PROJECT_SOURCE_DIR}/src/filesystem.c
+++  ${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
+++  ${PROJECT_SOURCE_DIR}/src/string_view.c
+++)
+++set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
+++setup_include_and_definitions(utils)
+++
+++#
+++# library : unix_based_hardware_detection
+++#
+++
+++if(UNIX)
+++  add_library(unix_based_hardware_detection OBJECT
+++    ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
+++    ${PROJECT_SOURCE_DIR}/src/hwcaps.c
+++  )
+++  setup_include_and_definitions(unix_based_hardware_detection)
+++  check_include_file(dlfcn.h HAVE_DLFCN_H)
+++  if(HAVE_DLFCN_H)
+++    target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H)
+++  endif()
+++  check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL)
+++  if(HAVE_STRONG_GETAUXVAL)
+++    target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
+++  endif()
+++  set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
+++endif()
+++
+++#
+++# library : cpu_features
+++#
+++set (CPU_FEATURES_HDRS)
+++set (CPU_FEATURES_SRCS)
+++add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS)
+++list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:utils>)
+++if(NOT PROCESSOR_IS_X86 AND UNIX)
+++  list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:unix_based_hardware_detection>)
+++endif()
+++add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS})
+++set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}")
+++setup_include_and_definitions(cpu_features)
+++target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
+++set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
+++target_include_directories(cpu_features
+++  PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
+++)
+++if(PROCESSOR_IS_X86)
+++  if(APPLE)
+++    target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
+++  endif()
+++endif()
+++add_library(CpuFeature::cpu_features ALIAS cpu_features)
+++
+++#
+++# program : list_cpu_features
+++#
+++
+++add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c)
+++target_link_libraries(list_cpu_features PRIVATE cpu_features)
+++add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features)
+++
+++#
+++# ndk_compat
+++#
+++
+++if(ANDROID)
+++add_subdirectory(ndk_compat)
+++endif()
+++
+++#
+++# tests
+++#
+++
+++include(CTest)
+++if(BUILD_TESTING)
+++  # Automatically incorporate googletest into the CMake Project if target not
+++  # found.
+++  enable_language(CXX)
+++
+++  set(CMAKE_CXX_STANDARD 11)
+++  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+++  set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
+++
+++  if(NOT TARGET gtest OR NOT TARGET gmock_main)
+++    # Download and unpack googletest at configure time.
+++    configure_file(
+++      cmake/googletest.CMakeLists.txt.in
+++      googletest-download/CMakeLists.txt
+++    )
+++
+++    execute_process(
+++      COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+++      RESULT_VARIABLE result
+++      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
+++
+++    if(result)
+++      message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+++    endif()
+++
+++    execute_process(
+++      COMMAND ${CMAKE_COMMAND} --build .
+++      RESULT_VARIABLE result
+++      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
+++
+++    if(result)
+++      message(FATAL_ERROR "Build step for googletest failed: ${result}")
+++    endif()
+++
+++    # Prevent overriding the parent project's compiler/linker settings on
+++    # Windows.
+++    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+++
+++    # Add googletest directly to our build. This defines the gtest and
+++    # gtest_main targets.
+++    add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
+++                     ${CMAKE_BINARY_DIR}/googletest-build
+++                     EXCLUDE_FROM_ALL)
+++  endif()
+++
+++  add_subdirectory(test)
+++endif()
+++
+++#
+++# Install cpu_features and list_cpu_features
+++#
+++
+++include(GNUInstallDirs)
+++install(TARGETS cpu_features list_cpu_features
+++  EXPORT CpuFeaturesTargets
+++  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features
+++  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+++  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+++  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+++)
+++install(EXPORT CpuFeaturesTargets
+++  NAMESPACE CpuFeatures::
+++  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures
+++  COMPONENT Devel
+++)
+++include(CMakePackageConfigHelpers)
+++configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in
+++  "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
+++  INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
+++  NO_SET_AND_CHECK_MACRO
+++  NO_CHECK_REQUIRED_COMPONENTS_MACRO
+++)
+++write_basic_package_version_file(
+++  "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
+++  COMPATIBILITY SameMajorVersion
+++)
+++install(
+++  FILES
+++    "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
+++    "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
+++  DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
+++  COMPONENT Devel
+++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c980350f8fc35cbde435c83412fb225335af7638
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,23 @@@@
+++# How to Contribute
+++
+++We'd love to accept your patches and contributions to this project. There are
+++just a few small guidelines you need to follow.
+++
+++## Contributor License Agreement
+++
+++Contributions to this project must be accompanied by a Contributor License
+++Agreement. You (or your employer) retain the copyright to your contribution;
+++this simply gives us permission to use and redistribute your contributions as
+++part of the project. Head over to <https://cla.developers.google.com/> to see
+++your current agreements on file or to sign a new one.
+++
+++You generally only need to submit a CLA once, so if you've already submitted one
+++(even if it was for a different project), you probably don't need to do it
+++again.
+++
+++## Code reviews
+++
+++All submissions, including submissions by project members, require review. We
+++use GitHub pull requests for this purpose. Consult
+++[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+++information on using pull requests.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a7043c6fdedacc991803384333201058ea1a8865
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,230 @@@@
+++
+++                                 Apache License
+++                           Version 2.0, January 2004
+++                        http://www.apache.org/licenses/
+++
+++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+++
+++   1. Definitions.
+++
+++      "License" shall mean the terms and conditions for use, reproduction,
+++      and distribution as defined by Sections 1 through 9 of this document.
+++
+++      "Licensor" shall mean the copyright owner or entity authorized by
+++      the copyright owner that is granting the License.
+++
+++      "Legal Entity" shall mean the union of the acting entity and all
+++      other entities that control, are controlled by, or are under common
+++      control with that entity. For the purposes of this definition,
+++      "control" means (i) the power, direct or indirect, to cause the
+++      direction or management of such entity, whether by contract or
+++      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+++      outstanding shares, or (iii) beneficial ownership of such entity.
+++
+++      "You" (or "Your") shall mean an individual or Legal Entity
+++      exercising permissions granted by this License.
+++
+++      "Source" form shall mean the preferred form for making modifications,
+++      including but not limited to software source code, documentation
+++      source, and configuration files.
+++
+++      "Object" form shall mean any form resulting from mechanical
+++      transformation or translation of a Source form, including but
+++      not limited to compiled object code, generated documentation,
+++      and conversions to other media types.
+++
+++      "Work" shall mean the work of authorship, whether in Source or
+++      Object form, made available under the License, as indicated by a
+++      copyright notice that is included in or attached to the work
+++      (an example is provided in the Appendix below).
+++
+++      "Derivative Works" shall mean any work, whether in Source or Object
+++      form, that is based on (or derived from) the Work and for which the
+++      editorial revisions, annotations, elaborations, or other modifications
+++      represent, as a whole, an original work of authorship. For the purposes
+++      of this License, Derivative Works shall not include works that remain
+++      separable from, or merely link (or bind by name) to the interfaces of,
+++      the Work and Derivative Works thereof.
+++
+++      "Contribution" shall mean any work of authorship, including
+++      the original version of the Work and any modifications or additions
+++      to that Work or Derivative Works thereof, that is intentionally
+++      submitted to Licensor for inclusion in the Work by the copyright owner
+++      or by an individual or Legal Entity authorized to submit on behalf of
+++      the copyright owner. For the purposes of this definition, "submitted"
+++      means any form of electronic, verbal, or written communication sent
+++      to the Licensor or its representatives, including but not limited to
+++      communication on electronic mailing lists, source code control systems,
+++      and issue tracking systems that are managed by, or on behalf of, the
+++      Licensor for the purpose of discussing and improving the Work, but
+++      excluding communication that is conspicuously marked or otherwise
+++      designated in writing by the copyright owner as "Not a Contribution."
+++
+++      "Contributor" shall mean Licensor and any individual or Legal Entity
+++      on behalf of whom a Contribution has been received by Licensor and
+++      subsequently incorporated within the Work.
+++
+++   2. Grant of Copyright License. Subject to the terms and conditions of
+++      this License, each Contributor hereby grants to You a perpetual,
+++      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+++      copyright license to reproduce, prepare Derivative Works of,
+++      publicly display, publicly perform, sublicense, and distribute the
+++      Work and such Derivative Works in Source or Object form.
+++
+++   3. Grant of Patent License. Subject to the terms and conditions of
+++      this License, each Contributor hereby grants to You a perpetual,
+++      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+++      (except as stated in this section) patent license to make, have made,
+++      use, offer to sell, sell, import, and otherwise transfer the Work,
+++      where such license applies only to those patent claims licensable
+++      by such Contributor that are necessarily infringed by their
+++      Contribution(s) alone or by combination of their Contribution(s)
+++      with the Work to which such Contribution(s) was submitted. If You
+++      institute patent litigation against any entity (including a
+++      cross-claim or counterclaim in a lawsuit) alleging that the Work
+++      or a Contribution incorporated within the Work constitutes direct
+++      or contributory patent infringement, then any patent licenses
+++      granted to You under this License for that Work shall terminate
+++      as of the date such litigation is filed.
+++
+++   4. Redistribution. You may reproduce and distribute copies of the
+++      Work or Derivative Works thereof in any medium, with or without
+++      modifications, and in Source or Object form, provided that You
+++      meet the following conditions:
+++
+++      (a) You must give any other recipients of the Work or
+++          Derivative Works a copy of this License; and
+++
+++      (b) You must cause any modified files to carry prominent notices
+++          stating that You changed the files; and
+++
+++      (c) You must retain, in the Source form of any Derivative Works
+++          that You distribute, all copyright, patent, trademark, and
+++          attribution notices from the Source form of the Work,
+++          excluding those notices that do not pertain to any part of
+++          the Derivative Works; and
+++
+++      (d) If the Work includes a "NOTICE" text file as part of its
+++          distribution, then any Derivative Works that You distribute must
+++          include a readable copy of the attribution notices contained
+++          within such NOTICE file, excluding those notices that do not
+++          pertain to any part of the Derivative Works, in at least one
+++          of the following places: within a NOTICE text file distributed
+++          as part of the Derivative Works; within the Source form or
+++          documentation, if provided along with the Derivative Works; or,
+++          within a display generated by the Derivative Works, if and
+++          wherever such third-party notices normally appear. The contents
+++          of the NOTICE file are for informational purposes only and
+++          do not modify the License. You may add Your own attribution
+++          notices within Derivative Works that You distribute, alongside
+++          or as an addendum to the NOTICE text from the Work, provided
+++          that such additional attribution notices cannot be construed
+++          as modifying the License.
+++
+++      You may add Your own copyright statement to Your modifications and
+++      may provide additional or different license terms and conditions
+++      for use, reproduction, or distribution of Your modifications, or
+++      for any such Derivative Works as a whole, provided Your use,
+++      reproduction, and distribution of the Work otherwise complies with
+++      the conditions stated in this License.
+++
+++   5. Submission of Contributions. Unless You explicitly state otherwise,
+++      any Contribution intentionally submitted for inclusion in the Work
+++      by You to the Licensor shall be under the terms and conditions of
+++      this License, without any additional terms or conditions.
+++      Notwithstanding the above, nothing herein shall supersede or modify
+++      the terms of any separate license agreement you may have executed
+++      with Licensor regarding such Contributions.
+++
+++   6. Trademarks. This License does not grant permission to use the trade
+++      names, trademarks, service marks, or product names of the Licensor,
+++      except as required for reasonable and customary use in describing the
+++      origin of the Work and reproducing the content of the NOTICE file.
+++
+++   7. Disclaimer of Warranty. Unless required by applicable law or
+++      agreed to in writing, Licensor provides the Work (and each
+++      Contributor provides its Contributions) on an "AS IS" BASIS,
+++      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+++      implied, including, without limitation, any warranties or conditions
+++      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+++      PARTICULAR PURPOSE. You are solely responsible for determining the
+++      appropriateness of using or redistributing the Work and assume any
+++      risks associated with Your exercise of permissions under this License.
+++
+++   8. Limitation of Liability. In no event and under no legal theory,
+++      whether in tort (including negligence), contract, or otherwise,
+++      unless required by applicable law (such as deliberate and grossly
+++      negligent acts) or agreed to in writing, shall any Contributor be
+++      liable to You for damages, including any direct, indirect, special,
+++      incidental, or consequential damages of any character arising as a
+++      result of this License or out of the use or inability to use the
+++      Work (including but not limited to damages for loss of goodwill,
+++      work stoppage, computer failure or malfunction, or any and all
+++      other commercial damages or losses), even if such Contributor
+++      has been advised of the possibility of such damages.
+++
+++   9. Accepting Warranty or Additional Liability. While redistributing
+++      the Work or Derivative Works thereof, You may choose to offer,
+++      and charge a fee for, acceptance of support, warranty, indemnity,
+++      or other liability obligations and/or rights consistent with this
+++      License. However, in accepting such obligations, You may act only
+++      on Your own behalf and on Your sole responsibility, not on behalf
+++      of any other Contributor, and only if You agree to indemnify,
+++      defend, and hold each Contributor harmless for any liability
+++      incurred by, or claims asserted against, such Contributor by reason
+++      of your accepting any such warranty or additional liability.
+++
+++   END OF TERMS AND CONDITIONS
+++
+++   APPENDIX: How to apply the Apache License to your work.
+++
+++      To apply the Apache License to your work, attach the following
+++      boilerplate notice, with the fields enclosed by brackets "[]"
+++      replaced with your own identifying information. (Don't include
+++      the brackets!)  The text should be enclosed in the appropriate
+++      comment syntax for the file format. We also recommend that a
+++      file or class name and description of purpose be included on the
+++      same "printed page" as the copyright notice for easier
+++      identification within third-party archives.
+++
+++   Copyright [yyyy] [name of copyright owner]
+++
+++   Licensed under the Apache License, Version 2.0 (the "License");
+++   you may not use this file except in compliance with the License.
+++   You may obtain a copy of the License at
+++
+++       http://www.apache.org/licenses/LICENSE-2.0
+++
+++   Unless required by applicable law or agreed to in writing, software
+++   distributed under the License is distributed on an "AS IS" BASIS,
+++   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++   See the License for the specific language governing permissions and
+++   limitations under the License.
+++
+++--------------------------------------------------------------------------------
+++For files in the `ndk_compat` folder:
+++--------------------------------------------------------------------------------
+++
+++Copyright (C) 2010 The Android Open Source Project
+++All rights reserved.
+++Redistribution and use in source and binary forms, with or without
+++modification, are permitted provided that the following conditions
+++are met:
+++ * Redistributions of source code must retain the above copyright
+++   notice, this list of conditions and the following disclaimer.
+++ * Redistributions in binary form must reproduce the above copyright
+++   notice, this list of conditions and the following disclaimer in
+++   the documentation and/or other materials provided with the
+++   distribution.
+++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+++SUCH DAMAGE.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8a3416859b86d65856418da0d6637e4070521acb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,199 @@@@
+++# cpu_features [![Build Status](https://travis-ci.org/google/cpu_features.svg?branch=master)](https://travis-ci.org/google/cpu_features) [![Build status](https://ci.appveyor.com/api/projects/status/46d1owsj7n8dsylq/branch/master?svg=true)](https://ci.appveyor.com/project/gchatelet/cpu-features/branch/master)
+++
+++A cross-platform C library to retrieve CPU features (such as available
+++instructions) at runtime.
+++
+++## Table of Contents
+++
+++- [Design Rationale](#rationale)
+++- [Code samples](#codesample)
+++- [Running sample code](#usagesample)
+++- [What's supported](#support)
+++- [Android NDK's drop in replacement](#ndk)
+++- [License](#license)
+++- [Build with cmake](#cmake)
+++
+++<a name="rationale"></a>
+++## Design Rationale
+++
+++-   **Simple to use.** See the snippets below for examples.
+++-   **Extensible.** Easy to add missing features or architectures.
+++-   **Compatible with old compilers** and available on many architectures so it
+++    can be used widely. To ensure that cpu_features works on as many platforms
+++    as possible, we implemented it in a highly portable version of C: C99.
+++-   **Sandbox-compatible.** The library uses a variety of strategies to cope
+++    with sandboxed environments or when `cpuid` is unavailable. This is useful
+++    when running integration tests in hermetic environments.
+++-   **Thread safe, no memory allocation, and raises no exceptions.**
+++    cpu_features is suitable for implementing fundamental libc functions like
+++    `malloc`, `memcpy`, and `memcmp`.
+++-   **Unit tested.**
+++
+++<a name="codesample"></a>
+++## Code samples
+++
+++**Note:** For C++ code, the library functions are defined in the `CpuFeatures` namespace.
+++
+++### Checking features at runtime
+++
+++Here's a simple example that executes a codepath if the CPU supports both the
+++AES and the SSE4.2 instruction sets:
+++
+++```c
+++#include "cpuinfo_x86.h"
+++
+++// For C++, add `using namespace CpuFeatures;`
+++static const X86Features features = GetX86Info().features;
+++
+++void Compute(void) {
+++  if (features.aes && features.sse4_2) {
+++    // Run optimized code.
+++  } else {
+++    // Run standard code.
+++  }
+++}
+++```
+++
+++### Caching for faster evaluation of complex checks
+++
+++If you wish, you can read all the features at once into a global variable, and
+++then query for the specific features you care about. Below, we store all the ARM
+++features and then check whether AES and NEON are supported.
+++
+++```c
+++#include <stdbool.h>
+++#include "cpuinfo_arm.h"
+++
+++// For C++, add `using namespace CpuFeatures;`
+++static const ArmFeatures features = GetArmInfo().features;
+++static const bool has_aes_and_neon = features.aes && features.neon;
+++
+++// use has_aes_and_neon.
+++```
+++
+++This is a good approach to take if you're checking for combinations of features
+++when using a compiler that is slow to extract individual bits from bit-packed
+++structures.
+++
+++### Checking compile time flags
+++
+++The following code determines whether the compiler was told to use the AVX
+++instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
+++
+++```c
+++#include <stdbool.h>
+++#include "cpuinfo_x86.h"
+++
+++// For C++, add `using namespace CpuFeatures;`
+++static const X86Features features = GetX86Info().features;
+++static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
+++
+++// use has_avx.
+++```
+++
+++`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to
+++use AVX and 0 otherwise, combining compile time and runtime knowledge.
+++
+++### Rejecting poor hardware implementations based on microarchitecture
+++
+++On x86, the first incarnation of a feature in a microarchitecture might not be
+++the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve
+++the underlying microarchitecture so you can decide whether to use it.
+++
+++Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction
+++set&mdash;but only if it's not Sandy Bridge.
+++
+++```c
+++#include <stdbool.h>
+++#include "cpuinfo_x86.h"
+++
+++// For C++, add `using namespace CpuFeatures;`
+++static const X86Info info = GetX86Info();
+++static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
+++static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
+++
+++// use has_fast_avx.
+++```
+++
+++This feature is currently available only for x86 microarchitectures.
+++
+++<a name="usagesample"></a>
+++### Running sample code
+++
+++Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
+++
+++```shell
+++ % ./build/list_cpu_features
+++arch            : x86
+++brand           :        Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz
+++family          :   6 (0x06)
+++model           :  45 (0x2D)
+++stepping        :   7 (0x07)
+++uarch           : INTEL_SNB
+++flags           : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
+++```
+++
+++```shell
+++% ./build/list_cpu_features --json
+++{"arch":"x86","brand":"       Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
+++```
+++
+++<a name="support"></a>
+++## What's supported
+++
+++|         | x86³ |   ARM   | AArch64 |  MIPS⁴ |  POWER  |
+++|---------|:----:|:-------:|:-------:|:------:|:-------:|
+++| Android | yes² |   yes¹  |   yes¹  |  yes¹  |   N/A   |
+++| iOS     |  N/A | not yet | not yet |   N/A  |   N/A   |
+++| Linux   | yes² |   yes¹  |   yes¹  |  yes¹  |   yes¹  |
+++| MacOs   | yes² |   N/A   | not yet |   N/A  |    no   |
+++| Windows | yes² | not yet | not yet |   N/A  |   N/A   |
+++
+++1.  **Features revealed from Linux.** We gather data from several sources
+++    depending on availability:
+++    +   from glibc's
+++        [getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html)
+++    +   by parsing `/proc/self/auxv`
+++    +   by parsing `/proc/cpuinfo`
+++2.  **Features revealed from CPU.** features are retrieved by using the `cpuid`
+++    instruction.
+++3.  **Microarchitecture detection.** On x86 some features are not always
+++    implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the
+++    microarchitecture allows the client to reject particular microarchitectures.
+++4.  All flavors of Mips are supported, little and big endian as well as 32/64
+++    bits.
+++
+++<a name="ndk"></a>
+++## Android NDK's drop in replacement
+++
+++[cpu_features](https://github.com/google/cpu_features) is now officially
+++supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h)
+++, see [ndk_compat](ndk_compat) folder for details.
+++
+++<a name="license"></a>
+++## License
+++
+++The cpu_features library is licensed under the terms of the Apache license.
+++See [LICENSE](LICENSE) for more information.
+++
+++<a name="cmake"></a>
+++## Build with CMake
+++
+++Please check the [CMake build instructions](cmake/README.md).
+++
+++<a name="quickstart"></a>
+++### Quickstart with `Ninja`
+++
+++ - build `list_cpu_features`
+++```
+++    cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release
+++    ninja -C/tmp/cpu_features
+++    /tmp/cpu_features/list_cpu_features --json
+++```
+++
+++ - run tests
+++```
+++    cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON
+++    ninja -C/tmp/cpu_features
+++    ninja -C/tmp/cpu_features test
+++```
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8ea8a8b6c59b81331ba029fe37d3b2f53be353aa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,7 @@@@
+++# ===== googletest =====
+++
+++git_repository(
+++    name = "com_google_googletest",
+++    remote = "https://github.com/google/googletest.git",
+++    commit = "c3f65335b79f47b05629e79a54685d899bc53b93",
+++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f18635a3d1956e6a64c831007dbd48cbe777e673
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,24 @@@@
+++version: '{build}'
+++shallow_clone: true
+++
+++platform: x64
+++
+++environment:
+++  matrix:
+++  - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+++    CMAKE_GENERATOR: "Visual Studio 15 2017 Win64"
+++  - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+++    CMAKE_GENERATOR: "Visual Studio 14 2015 Win64"
+++
+++matrix:
+++  fast_finish: true
+++
+++before_build:
+++  - cmake --version
+++  - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -H. -Bcmake_build -G "%CMAKE_GENERATOR%"
+++
+++build_script:
+++  - cmake --build cmake_build --config Debug --target ALL_BUILD
+++
+++test_script:
+++  - cmake --build cmake_build --config Debug --target RUN_TESTS
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e0bf10e42de1410c4b5cc5d307bea2565cfb320b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,3 @@@@
+++# CpuFeatures CMake configuration file
+++
+++include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake")
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5a53ffda9265e77988e85346c0d520a5571c426b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,3 @@@@
+++# CpuFeaturesNdkCompat CMake configuration file
+++
+++include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesNdkCompatTargets.cmake")
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b6baeaa21c8acc45cd2d74aede364dcddce3f8c0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,28 @@@@
+++# CMake build instructions
+++
+++## Recommended usage : Incorporating cpu_features into a CMake project
+++
+++  For API / ABI compatibility reasons, it is recommended to build and use
+++  cpu_features in a subdirectory of your project or as an embedded dependency.
+++
+++  This is similar to the recommended usage of the googletest framework
+++  ( https://github.com/google/googletest/blob/master/googletest/README.md )
+++
+++  Build and use step-by-step
+++
+++
+++  1- Download cpu_features and copy it in a sub-directory in your project.
+++      or add cpu_features as a git-submodule in your project
+++
+++  2- You can then use the cmake command `add_subdirectory()` to include
+++     cpu_features directly and use the `cpu_features` target in your project.
+++
+++  3- Add the `cpu_features` target to the `target_link_libraries()` section of
+++     your executable or of your library.
+++
+++## Enabling tests
+++
+++  CMake default options for cpu_features is Release built type with tests
+++  disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`,
+++  [.travis.yml](../.travis.yml) and [appveyor.yml](../appveyor.yml) have up to
+++  date examples.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d60a33e9ac6a6ddfe0ebd181b33743f95e67b5a5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,15 @@@@
+++cmake_minimum_required(VERSION 2.8.2)
+++
+++project(googletest-download NONE)
+++
+++include(ExternalProject)
+++ExternalProject_Add(googletest
+++  GIT_REPOSITORY    https://github.com/google/googletest.git
+++  GIT_TAG           master
+++  SOURCE_DIR        "${CMAKE_BINARY_DIR}/googletest-src"
+++  BINARY_DIR        "${CMAKE_BINARY_DIR}/googletest-build"
+++  CONFIGURE_COMMAND ""
+++  BUILD_COMMAND     ""
+++  INSTALL_COMMAND   ""
+++  TEST_COMMAND      ""
+++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1a61ee1e85fe7ccef113dbc84155a361153c1c79
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,54 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef enum {
+++  CPU_FEATURE_CACHE_NULL = 0,
+++  CPU_FEATURE_CACHE_DATA = 1,
+++  CPU_FEATURE_CACHE_INSTRUCTION = 2,
+++  CPU_FEATURE_CACHE_UNIFIED = 3,
+++  CPU_FEATURE_CACHE_TLB = 4,
+++  CPU_FEATURE_CACHE_DTLB = 5,
+++  CPU_FEATURE_CACHE_STLB = 6,
+++  CPU_FEATURE_CACHE_PREFETCH = 7
+++} CacheType;
+++
+++typedef struct {
+++  int level;
+++  CacheType cache_type;
+++  int cache_size;    // Cache size in bytes
+++  int ways;          // Associativity, 0 undefined, 0xFF fully associative
+++  int line_size;     // Cache line size in bytes
+++  int tlb_entries;   // number of entries for TLB
+++  int partitioning;  // number of lines per sector
+++} CacheLevelInfo;
+++
+++// Increase this value if more cache levels are needed.
+++#ifndef CPU_FEATURES_MAX_CACHE_LEVEL
+++#define CPU_FEATURES_MAX_CACHE_LEVEL 10
+++#endif
+++typedef struct {
+++  int size;
+++  CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL];
+++} CacheInfo;
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4b231a185e1cfa6a55c9bc7e3d692564f9c86bb5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,216 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
+++#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Architectures
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#if defined(__pnacl__) || defined(__CLR_VER)
+++#define CPU_FEATURES_ARCH_VM
+++#endif
+++
+++#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM)
+++#define CPU_FEATURES_ARCH_X86_32
+++#endif
+++
+++#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM)
+++#define CPU_FEATURES_ARCH_X86_64
+++#endif
+++
+++#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64)
+++#define CPU_FEATURES_ARCH_X86
+++#endif
+++
+++#if (defined(__arm__) || defined(_M_ARM))
+++#define CPU_FEATURES_ARCH_ARM
+++#endif
+++
+++#if defined(__aarch64__)
+++#define CPU_FEATURES_ARCH_AARCH64
+++#endif
+++
+++#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM))
+++#define CPU_FEATURES_ARCH_ANY_ARM
+++#endif
+++
+++#if defined(__mips64)
+++#define CPU_FEATURES_ARCH_MIPS64
+++#endif
+++
+++#if defined(__mips__) && !defined(__mips64)  // mips64 also declares __mips__
+++#define CPU_FEATURES_ARCH_MIPS32
+++#endif
+++
+++#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64)
+++#define CPU_FEATURES_ARCH_MIPS
+++#endif
+++
+++#if defined(__powerpc__)
+++#define CPU_FEATURES_ARCH_PPC
+++#endif
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Os
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#if defined(__linux__)
+++#define CPU_FEATURES_OS_LINUX_OR_ANDROID
+++#endif
+++
+++#if defined(__ANDROID__)
+++#define CPU_FEATURES_OS_ANDROID
+++#endif
+++
+++#if (defined(_WIN64) || defined(_WIN32))
+++#define CPU_FEATURES_OS_WINDOWS
+++#endif
+++
+++#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
+++#define CPU_FEATURES_OS_DARWIN
+++#endif
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Compilers
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#if defined(__clang__)
+++#define CPU_FEATURES_COMPILER_CLANG
+++#endif
+++
+++#if defined(__GNUC__) && !defined(__clang__)
+++#define CPU_FEATURES_COMPILER_GCC
+++#endif
+++
+++#if defined(_MSC_VER)
+++#define CPU_FEATURES_COMPILER_MSC
+++#endif
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Cpp
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#if defined(__cplusplus)
+++#define CPU_FEATURES_START_CPP_NAMESPACE \
+++  namespace cpu_features {               \
+++  extern "C" {
+++#define CPU_FEATURES_END_CPP_NAMESPACE \
+++  }                                    \
+++  }
+++#else
+++#define CPU_FEATURES_START_CPP_NAMESPACE
+++#define CPU_FEATURES_END_CPP_NAMESPACE
+++#endif
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Compiler flags
+++////////////////////////////////////////////////////////////////////////////////
+++
+++// Use the following to check if a feature is known to be available at
+++// compile time. See README.md for an example.
+++#if defined(CPU_FEATURES_ARCH_X86)
+++
+++#if defined(__AES__)
+++#define CPU_FEATURES_COMPILED_X86_AES 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_AES 0
+++#endif  //  defined(__AES__)
+++
+++#if defined(__F16C__)
+++#define CPU_FEATURES_COMPILED_X86_F16C 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_F16C 0
+++#endif  //  defined(__F16C__)
+++
+++#if defined(__BMI__)
+++#define CPU_FEATURES_COMPILED_X86_BMI 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_BMI 0
+++#endif  //  defined(__BMI__)
+++
+++#if defined(__BMI2__)
+++#define CPU_FEATURES_COMPILED_X86_BMI2 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_BMI2 0
+++#endif  //  defined(__BMI2__)
+++
+++#if (defined(__SSE__) || (_M_IX86_FP >= 1))
+++#define CPU_FEATURES_COMPILED_X86_SSE 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSE 0
+++#endif
+++
+++#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
+++#define CPU_FEATURES_COMPILED_X86_SSE2 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSE2 0
+++#endif
+++
+++#if defined(__SSE3__)
+++#define CPU_FEATURES_COMPILED_X86_SSE3 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSE3 0
+++#endif  //  defined(__SSE3__)
+++
+++#if defined(__SSSE3__)
+++#define CPU_FEATURES_COMPILED_X86_SSSE3 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSSE3 0
+++#endif  //  defined(__SSSE3__)
+++
+++#if defined(__SSE4_1__)
+++#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
+++#endif  //  defined(__SSE4_1__)
+++
+++#if defined(__SSE4_2__)
+++#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
+++#endif  //  defined(__SSE4_2__)
+++
+++#if defined(__AVX__)
+++#define CPU_FEATURES_COMPILED_X86_AVX 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_AVX 0
+++#endif  //  defined(__AVX__)
+++
+++#if defined(__AVX2__)
+++#define CPU_FEATURES_COMPILED_X86_AVX2 1
+++#else
+++#define CPU_FEATURES_COMPILED_X86_AVX2 0
+++#endif  //  defined(__AVX2__)
+++
+++#endif  // defined(CPU_FEATURES_ARCH_X86)
+++
+++#if defined(CPU_FEATURES_ARCH_ANY_ARM)
+++#if defined(__ARM_NEON__)
+++#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
+++#else
+++#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
+++#endif  //  defined(__ARM_NEON__)
+++#endif  //  defined(CPU_FEATURES_ARCH_ANY_ARM)
+++
+++#if defined(CPU_FEATURES_ARCH_MIPS)
+++#if defined(__mips_msa)
+++#define CPU_FEATURES_COMPILED_MIPS_MSA 1
+++#else
+++#define CPU_FEATURES_COMPILED_MIPS_MSA 0
+++#endif  //  defined(__mips_msa)
+++#endif  //  defined(CPU_FEATURES_ARCH_MIPS)
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d85d46d4a0eefcef43a3c1e4c7896dc16a0055e0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,156 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
+++
+++#include "cpu_features_cache_info.h"
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  int fp : 1;          // Floating-point.
+++  int asimd : 1;       // Advanced SIMD.
+++  int evtstrm : 1;     // Generic timer generated events.
+++  int aes : 1;         // Hardware-accelerated Advanced Encryption Standard.
+++  int pmull : 1;       // Polynomial multiply long.
+++  int sha1 : 1;        // Hardware-accelerated SHA1.
+++  int sha2 : 1;        // Hardware-accelerated SHA2-256.
+++  int crc32 : 1;       // Hardware-accelerated CRC-32.
+++  int atomics : 1;     // Armv8.1 atomic instructions.
+++  int fphp : 1;        // Half-precision floating point support.
+++  int asimdhp : 1;     // Advanced SIMD half-precision support.
+++  int cpuid : 1;       // Access to certain ID registers.
+++  int asimdrdm : 1;    // Rounding Double Multiply Accumulate/Subtract.
+++  int jscvt : 1;       // Support for JavaScript conversion.
+++  int fcma : 1;        // Floating point complex numbers.
+++  int lrcpc : 1;       // Support for weaker release consistency.
+++  int dcpop : 1;       // Data persistence writeback.
+++  int sha3 : 1;        // Hardware-accelerated SHA3.
+++  int sm3 : 1;         // Hardware-accelerated SM3.
+++  int sm4 : 1;         // Hardware-accelerated SM4.
+++  int asimddp : 1;     // Dot product instruction.
+++  int sha512 : 1;      // Hardware-accelerated SHA512.
+++  int sve : 1;         // Scalable Vector Extension.
+++  int asimdfhm : 1;    // Additional half-precision instructions.
+++  int dit : 1;         // Data independent timing.
+++  int uscat : 1;       // Unaligned atomics support.
+++  int ilrcpc : 1;      // Additional support for weaker release consistency.
+++  int flagm : 1;       // Flag manipulation instructions.
+++  int ssbs : 1;        // Speculative Store Bypass Safe PSTATE bit.
+++  int sb : 1;          // Speculation barrier.
+++  int paca : 1;        // Address authentication.
+++  int pacg : 1;        // Generic authentication.
+++  int dcpodp : 1;      // Data cache clean to point of persistence.
+++  int sve2 : 1;        // Scalable Vector Extension (version 2).
+++  int sveaes : 1;      // SVE AES instructions.
+++  int svepmull : 1;    // SVE polynomial multiply long instructions.
+++  int svebitperm : 1;  // SVE bit permute instructions.
+++  int svesha3 : 1;     // SVE SHA3 instructions.
+++  int svesm4 : 1;      // SVE SM4 instructions.
+++  int flagm2 : 1;      // Additional flag manipulation instructions.
+++  int frint : 1;       // Floating point to integer rounding.
+++  int svei8mm : 1;     // SVE Int8 matrix multiplication instructions.
+++  int svef32mm : 1;    // SVE FP32 matrix multiplication instruction.
+++  int svef64mm : 1;    // SVE FP64 matrix multiplication instructions.
+++  int svebf16 : 1;     // SVE BFloat16 instructions.
+++  int i8mm : 1;        // Int8 matrix multiplication instructions.
+++  int bf16 : 1;        // BFloat16 instructions.
+++  int dgh : 1;         // Data Gathering Hint instruction.
+++  int rng : 1;         // True random number generator support.
+++  int bti : 1;         // Branch target identification.
+++
+++  // Make sure to update Aarch64FeaturesEnum below if you add a field here.
+++} Aarch64Features;
+++
+++typedef struct {
+++  Aarch64Features features;
+++  int implementer;
+++  int variant;
+++  int part;
+++  int revision;
+++} Aarch64Info;
+++
+++Aarch64Info GetAarch64Info(void);
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++typedef enum {
+++  AARCH64_FP,
+++  AARCH64_ASIMD,
+++  AARCH64_EVTSTRM,
+++  AARCH64_AES,
+++  AARCH64_PMULL,
+++  AARCH64_SHA1,
+++  AARCH64_SHA2,
+++  AARCH64_CRC32,
+++  AARCH64_ATOMICS,
+++  AARCH64_FPHP,
+++  AARCH64_ASIMDHP,
+++  AARCH64_CPUID,
+++  AARCH64_ASIMDRDM,
+++  AARCH64_JSCVT,
+++  AARCH64_FCMA,
+++  AARCH64_LRCPC,
+++  AARCH64_DCPOP,
+++  AARCH64_SHA3,
+++  AARCH64_SM3,
+++  AARCH64_SM4,
+++  AARCH64_ASIMDDP,
+++  AARCH64_SHA512,
+++  AARCH64_SVE,
+++  AARCH64_ASIMDFHM,
+++  AARCH64_DIT,
+++  AARCH64_USCAT,
+++  AARCH64_ILRCPC,
+++  AARCH64_FLAGM,
+++  AARCH64_SSBS,
+++  AARCH64_SB,
+++  AARCH64_PACA,
+++  AARCH64_PACG,
+++  AARCH64_DCPODP,
+++  AARCH64_SVE2,
+++  AARCH64_SVEAES,
+++  AARCH64_SVEPMULL,
+++  AARCH64_SVEBITPERM,
+++  AARCH64_SVESHA3,
+++  AARCH64_SVESM4,
+++  AARCH64_FLAGM2,
+++  AARCH64_FRINT,
+++  AARCH64_SVEI8MM,
+++  AARCH64_SVEF32MM,
+++  AARCH64_SVEF64MM,
+++  AARCH64_SVEBF16,
+++  AARCH64_I8MM,
+++  AARCH64_BF16,
+++  AARCH64_DGH,
+++  AARCH64_RNG,
+++  AARCH64_BTI,
+++  AARCH64_LAST_,
+++} Aarch64FeaturesEnum;
+++
+++int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
+++                                Aarch64FeaturesEnum value);
+++
+++const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#if !defined(CPU_FEATURES_ARCH_AARCH64)
+++#error "Including cpuinfo_aarch64.h from a non-aarch64 target."
+++#endif
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0952d7c2549c43a00cfc02aa1e3b5d589ce73991
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,121 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
+++
+++#include <stdint.h>  // uint32_t
+++
+++#include "cpu_features_cache_info.h"
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  int swp : 1;       // SWP instruction (atomic read-modify-write)
+++  int half : 1;      // Half-word loads and stores
+++  int thumb : 1;     // Thumb (16-bit instruction set)
+++  int _26bit : 1;    // "26 Bit" Model (Processor status register folded into
+++                     // program counter)
+++  int fastmult : 1;  // 32x32->64-bit multiplication
+++  int fpa : 1;       // Floating point accelerator
+++  int vfp : 1;       // Vector Floating Point.
+++  int edsp : 1;     // DSP extensions (the 'e' variant of the ARM9 CPUs, and all
+++                    // others above)
+++  int java : 1;     // Jazelle (Java bytecode accelerator)
+++  int iwmmxt : 1;   // Intel Wireless MMX Technology.
+++  int crunch : 1;   // MaverickCrunch coprocessor
+++  int thumbee : 1;  // ThumbEE
+++  int neon : 1;     // Advanced SIMD.
+++  int vfpv3 : 1;    // VFP version 3
+++  int vfpv3d16 : 1;  // VFP version 3 with 16 D-registers
+++  int tls : 1;       // TLS register
+++  int vfpv4 : 1;     // VFP version 4 with fast context switching
+++  int idiva : 1;     // SDIV and UDIV hardware division in ARM mode.
+++  int idivt : 1;     // SDIV and UDIV hardware division in Thumb mode.
+++  int vfpd32 : 1;    // VFP with 32 D-registers
+++  int lpae : 1;     // Large Physical Address Extension (>4GB physical memory on
+++                    // 32-bit architecture)
+++  int evtstrm : 1;  // kernel event stream using generic architected timer
+++  int aes : 1;      // Hardware-accelerated Advanced Encryption Standard.
+++  int pmull : 1;    // Polynomial multiply long.
+++  int sha1 : 1;     // Hardware-accelerated SHA1.
+++  int sha2 : 1;     // Hardware-accelerated SHA2-256.
+++  int crc32 : 1;    // Hardware-accelerated CRC-32.
+++
+++  // Make sure to update ArmFeaturesEnum below if you add a field here.
+++} ArmFeatures;
+++
+++typedef struct {
+++  ArmFeatures features;
+++  int implementer;
+++  int architecture;
+++  int variant;
+++  int part;
+++  int revision;
+++} ArmInfo;
+++
+++// TODO(user): Add macros to know which features are present at compile
+++// time.
+++
+++ArmInfo GetArmInfo(void);
+++
+++// Compute CpuId from ArmInfo.
+++uint32_t GetArmCpuId(const ArmInfo* const info);
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++typedef enum {
+++  ARM_SWP,
+++  ARM_HALF,
+++  ARM_THUMB,
+++  ARM_26BIT,
+++  ARM_FASTMULT,
+++  ARM_FPA,
+++  ARM_VFP,
+++  ARM_EDSP,
+++  ARM_JAVA,
+++  ARM_IWMMXT,
+++  ARM_CRUNCH,
+++  ARM_THUMBEE,
+++  ARM_NEON,
+++  ARM_VFPV3,
+++  ARM_VFPV3D16,
+++  ARM_TLS,
+++  ARM_VFPV4,
+++  ARM_IDIVA,
+++  ARM_IDIVT,
+++  ARM_VFPD32,
+++  ARM_LPAE,
+++  ARM_EVTSTRM,
+++  ARM_AES,
+++  ARM_PMULL,
+++  ARM_SHA1,
+++  ARM_SHA2,
+++  ARM_CRC32,
+++  ARM_LAST_,
+++} ArmFeaturesEnum;
+++
+++int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value);
+++
+++const char* GetArmFeaturesEnumName(ArmFeaturesEnum);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#if !defined(CPU_FEATURES_ARCH_ARM)
+++#error "Including cpuinfo_arm.h from a non-arm target."
+++#endif
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9e5e7fc5706001b0232a4c150ce86afea2faa423
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,60 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
+++
+++#include "cpu_features_cache_info.h"
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  int msa : 1;  // MIPS SIMD Architecture
+++                // https://www.mips.com/products/architectures/ase/simd/
+++  int eva : 1;  // Enhanced Virtual Addressing
+++                // https://www.mips.com/products/architectures/mips64/
+++  int r6 : 1;   // True if is release 6 of the processor.
+++
+++  // Make sure to update MipsFeaturesEnum below if you add a field here.
+++} MipsFeatures;
+++
+++typedef struct {
+++  MipsFeatures features;
+++} MipsInfo;
+++
+++MipsInfo GetMipsInfo(void);
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++typedef enum {
+++  MIPS_MSA,
+++  MIPS_EVA,
+++  MIPS_R6,
+++  MIPS_LAST_,
+++} MipsFeaturesEnum;
+++
+++int GetMipsFeaturesEnumValue(const MipsFeatures* features,
+++                             MipsFeaturesEnum value);
+++
+++const char* GetMipsFeaturesEnumName(MipsFeaturesEnum);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#if !defined(CPU_FEATURES_ARCH_MIPS)
+++#error "Including cpuinfo_mips.h from a non-mips target."
+++#endif
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f69119485d4e028ceabf01f1fce3d69c984012a2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,146 @@@@
+++// Copyright 2018 IBM
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
+++
+++#include "cpu_features_cache_info.h"
+++#include "cpu_features_macros.h"
+++#include "internal/hwcaps.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  int ppc32 : 1;
+++  int ppc64 : 1;
+++  int ppc601 : 1;
+++  int altivec : 1;
+++  int fpu : 1;
+++  int mmu : 1;
+++  int mac_4xx : 1;
+++  int unifiedcache : 1;
+++  int spe : 1;
+++  int efpsingle : 1;
+++  int efpdouble : 1;
+++  int no_tb : 1;
+++  int power4 : 1;
+++  int power5 : 1;
+++  int power5plus : 1;
+++  int cell : 1;
+++  int booke : 1;
+++  int smt : 1;
+++  int icachesnoop : 1;
+++  int arch205 : 1;
+++  int pa6t : 1;
+++  int dfp : 1;
+++  int power6ext : 1;
+++  int arch206 : 1;
+++  int vsx : 1;
+++  int pseries_perfmon_compat : 1;
+++  int truele : 1;
+++  int ppcle : 1;
+++  int arch207 : 1;
+++  int htm : 1;
+++  int dscr : 1;
+++  int ebb : 1;
+++  int isel : 1;
+++  int tar : 1;
+++  int vcrypto : 1;
+++  int htm_nosc : 1;
+++  int arch300 : 1;
+++  int ieee128 : 1;
+++  int darn : 1;
+++  int scv : 1;
+++  int htm_no_suspend : 1;
+++
+++  // Make sure to update PPCFeaturesEnum below if you add a field here.
+++} PPCFeatures;
+++
+++typedef struct {
+++  PPCFeatures features;
+++} PPCInfo;
+++
+++// This function is guaranteed to be malloc, memset and memcpy free.
+++PPCInfo GetPPCInfo(void);
+++
+++typedef struct {
+++  char platform[64];  // 0 terminated string
+++  char model[64];     // 0 terminated string
+++  char machine[64];   // 0 terminated string
+++  char cpu[64];       // 0 terminated string
+++  PlatformType type;
+++} PPCPlatformStrings;
+++
+++PPCPlatformStrings GetPPCPlatformStrings(void);
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++typedef enum {
+++  PPC_32,          /* 32 bit mode execution */
+++  PPC_64,          /* 64 bit mode execution */
+++  PPC_601_INSTR,   /* Old POWER ISA */
+++  PPC_HAS_ALTIVEC, /* SIMD Unit*/
+++  PPC_HAS_FPU,     /* Floating Point Unit */
+++  PPC_HAS_MMU,     /* Memory management unit */
+++  PPC_HAS_4xxMAC,
+++  PPC_UNIFIED_CACHE,  /* Unified instruction and data cache */
+++  PPC_HAS_SPE,        /* Signal processing extention unit */
+++  PPC_HAS_EFP_SINGLE, /* SPE single precision fpu */
+++  PPC_HAS_EFP_DOUBLE, /* SPE double precision fpu */
+++  PPC_NO_TB,          /* No timebase */
+++  PPC_POWER4,
+++  PPC_POWER5,
+++  PPC_POWER5_PLUS,
+++  PPC_CELL,  /* Cell broadband engine */
+++  PPC_BOOKE, /* Embedded ISA */
+++  PPC_SMT,   /* Simultaneous multi-threading */
+++  PPC_ICACHE_SNOOP,
+++  PPC_ARCH_2_05, /* ISA 2.05 - POWER6 */
+++  PPC_PA6T,      /* PA Semi 6T core ISA */
+++  PPC_HAS_DFP,   /* Decimal floating point unit */
+++  PPC_POWER6_EXT,
+++  PPC_ARCH_2_06,              /* ISA 2.06 - POWER7 */
+++  PPC_HAS_VSX,                /* Vector-scalar extension */
+++  PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance
+++                                 monitoring events */
+++  PPC_TRUE_LE,
+++  PPC_PPC_LE,
+++  PPC_ARCH_2_07,      /* ISA 2.07 - POWER8 */
+++  PPC_HTM,            /* Hardware Transactional Memory */
+++  PPC_DSCR,           /* Data stream control register */
+++  PPC_EBB,            /* Event base branching */
+++  PPC_ISEL,           /* Integer select instructions */
+++  PPC_TAR,            /* Target address register */
+++  PPC_VEC_CRYPTO,     /* Vector cryptography instructions */
+++  PPC_HTM_NOSC,       /* Transactions aborted when syscall made*/
+++  PPC_ARCH_3_00,      /* ISA 3.00 - POWER9 */
+++  PPC_HAS_IEEE128,    /* VSX IEEE Binary Float 128-bit */
+++  PPC_DARN,           /* Deliver a random number instruction */
+++  PPC_SCV,            /* scv syscall */
+++  PPC_HTM_NO_SUSPEND, /* TM w/out suspended state */
+++  PPC_LAST_,
+++} PPCFeaturesEnum;
+++
+++int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value);
+++
+++const char* GetPPCFeaturesEnumName(PPCFeaturesEnum);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#if !defined(CPU_FEATURES_ARCH_PPC)
+++#error "Including cpuinfo_ppc.h from a non-ppc target."
+++#endif
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8d40f71128d3f3a617dcb9f285213e8824676259
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,231 @@@@
+++// Copyright 2017 Google LLC
+++// Copyright 2020 Intel Corporation
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
+++#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
+++
+++#include "cpu_features_cache_info.h"
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features.
+++// The field names are based on the short name provided in the wikipedia tables.
+++typedef struct {
+++  int fpu : 1;
+++  int tsc : 1;
+++  int cx8 : 1;
+++  int clfsh : 1;
+++  int mmx : 1;
+++  int aes : 1;
+++  int erms : 1;
+++  int f16c : 1;
+++  int fma4 : 1;
+++  int fma3 : 1;
+++  int vaes : 1;
+++  int vpclmulqdq : 1;
+++  int bmi1 : 1;
+++  int hle : 1;
+++  int bmi2 : 1;
+++  int rtm : 1;
+++  int rdseed : 1;
+++  int clflushopt : 1;
+++  int clwb : 1;
+++
+++  int sse : 1;
+++  int sse2 : 1;
+++  int sse3 : 1;
+++  int ssse3 : 1;
+++  int sse4_1 : 1;
+++  int sse4_2 : 1;
+++  int sse4a : 1;
+++
+++  int avx : 1;
+++  int avx2 : 1;
+++
+++  int avx512f : 1;
+++  int avx512cd : 1;
+++  int avx512er : 1;
+++  int avx512pf : 1;
+++  int avx512bw : 1;
+++  int avx512dq : 1;
+++  int avx512vl : 1;
+++  int avx512ifma : 1;
+++  int avx512vbmi : 1;
+++  int avx512vbmi2 : 1;
+++  int avx512vnni : 1;
+++  int avx512bitalg : 1;
+++  int avx512vpopcntdq : 1;
+++  int avx512_4vnniw : 1;
+++  int avx512_4vbmi2 : 1;
+++  int avx512_second_fma : 1;
+++  int avx512_4fmaps : 1;
+++  int avx512_bf16 : 1;
+++  int avx512_vp2intersect : 1;
+++  int amx_bf16 : 1;
+++  int amx_tile : 1;
+++  int amx_int8 : 1;
+++
+++  int pclmulqdq : 1;
+++  int smx : 1;
+++  int sgx : 1;
+++  int cx16 : 1;  // aka. CMPXCHG16B
+++  int sha : 1;
+++  int popcnt : 1;
+++  int movbe : 1;
+++  int rdrnd : 1;
+++
+++  int dca : 1;
+++  int ss : 1;
+++  // Make sure to update X86FeaturesEnum below if you add a field here.
+++} X86Features;
+++
+++typedef struct {
+++  X86Features features;
+++  int family;
+++  int model;
+++  int stepping;
+++  char vendor[13];  // 0 terminated string
+++} X86Info;
+++
+++// Calls cpuid and returns an initialized X86info.
+++// This function is guaranteed to be malloc, memset and memcpy free.
+++X86Info GetX86Info(void);
+++
+++// Returns cache hierarchy informations.
+++// Can call cpuid multiple times.
+++// Only works on Intel CPU at the moment.
+++// This function is guaranteed to be malloc, memset and memcpy free.
+++CacheInfo GetX86CacheInfo(void);
+++
+++typedef enum {
+++  X86_UNKNOWN,
+++  INTEL_CORE,      // CORE
+++  INTEL_PNR,       // PENRYN
+++  INTEL_NHM,       // NEHALEM
+++  INTEL_ATOM_BNL,  // BONNELL
+++  INTEL_WSM,       // WESTMERE
+++  INTEL_SNB,       // SANDYBRIDGE
+++  INTEL_IVB,       // IVYBRIDGE
+++  INTEL_ATOM_SMT,  // SILVERMONT
+++  INTEL_HSW,       // HASWELL
+++  INTEL_BDW,       // BROADWELL
+++  INTEL_SKL,       // SKYLAKE
+++  INTEL_ATOM_GMT,  // GOLDMONT
+++  INTEL_KBL,       // KABY LAKE
+++  INTEL_CFL,       // COFFEE LAKE
+++  INTEL_WHL,       // WHISKEY LAKE
+++  INTEL_CNL,       // CANNON LAKE
+++  INTEL_ICL,       // ICE LAKE
+++  INTEL_TGL,       // TIGER LAKE
+++  INTEL_SPR,       // SAPPHIRE RAPIDS
+++  AMD_HAMMER,      // K8
+++  AMD_K10,         // K10
+++  AMD_BOBCAT,      // K14
+++  AMD_BULLDOZER,   // K15
+++  AMD_JAGUAR,      // K16
+++  AMD_ZEN,         // K17
+++} X86Microarchitecture;
+++
+++// Returns the underlying microarchitecture by looking at X86Info's vendor,
+++// family and model.
+++X86Microarchitecture GetX86Microarchitecture(const X86Info* info);
+++
+++// Calls cpuid and fills the brand_string.
+++// - brand_string *must* be of size 49 (beware of array decaying).
+++// - brand_string will be zero terminated.
+++// - This function calls memcpy.
+++void FillX86BrandString(char brand_string[49]);
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++typedef enum {
+++  X86_FPU,
+++  X86_TSC,
+++  X86_CX8,
+++  X86_CLFSH,
+++  X86_MMX,
+++  X86_AES,
+++  X86_ERMS,
+++  X86_F16C,
+++  X86_FMA4,
+++  X86_FMA3,
+++  X86_VAES,
+++  X86_VPCLMULQDQ,
+++  X86_BMI1,
+++  X86_HLE,
+++  X86_BMI2,
+++  X86_RTM,
+++  X86_RDSEED,
+++  X86_CLFLUSHOPT,
+++  X86_CLWB,
+++  X86_SSE,
+++  X86_SSE2,
+++  X86_SSE3,
+++  X86_SSSE3,
+++  X86_SSE4_1,
+++  X86_SSE4_2,
+++  X86_SSE4A,
+++  X86_AVX,
+++  X86_AVX2,
+++  X86_AVX512F,
+++  X86_AVX512CD,
+++  X86_AVX512ER,
+++  X86_AVX512PF,
+++  X86_AVX512BW,
+++  X86_AVX512DQ,
+++  X86_AVX512VL,
+++  X86_AVX512IFMA,
+++  X86_AVX512VBMI,
+++  X86_AVX512VBMI2,
+++  X86_AVX512VNNI,
+++  X86_AVX512BITALG,
+++  X86_AVX512VPOPCNTDQ,
+++  X86_AVX512_4VNNIW,
+++  X86_AVX512_4VBMI2,
+++  X86_AVX512_SECOND_FMA,
+++  X86_AVX512_4FMAPS,
+++  X86_AVX512_BF16,
+++  X86_AVX512_VP2INTERSECT,
+++  X86_AMX_BF16,
+++  X86_AMX_TILE,
+++  X86_AMX_INT8,
+++  X86_PCLMULQDQ,
+++  X86_SMX,
+++  X86_SGX,
+++  X86_CX16,
+++  X86_SHA,
+++  X86_POPCNT,
+++  X86_MOVBE,
+++  X86_RDRND,
+++  X86_DCA,
+++  X86_SS,
+++  X86_LAST_,
+++} X86FeaturesEnum;
+++
+++int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value);
+++
+++const char* GetX86FeaturesEnumName(X86FeaturesEnum);
+++
+++const char* GetX86MicroarchitectureName(X86Microarchitecture);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#if !defined(CPU_FEATURES_ARCH_X86)
+++#error "Including cpuinfo_x86.h from a non-x86 target."
+++#endif
+++
+++#endif  // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3467ff939955c9414f795acc2b9d38f494a3d6b8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,40 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
+++
+++#include <assert.h>
+++#include <stdbool.h>
+++#include <stdint.h>
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++inline static bool IsBitSet(uint32_t reg, uint32_t bit) {
+++  return (reg >> bit) & 0x1;
+++}
+++
+++inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb,
+++                                       uint32_t lsb) {
+++  const uint64_t bits = msb - lsb + 1ULL;
+++  const uint64_t mask = (1ULL << bits) - 1ULL;
+++  assert(msb >= lsb);
+++  return (reg >> lsb) & mask;
+++}
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..33327a47ba497c78ae8765386eba5de6ffcae09d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,37 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
+++
+++#include <stdint.h>
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++// A struct to hold the result of a call to cpuid.
+++typedef struct {
+++  uint32_t eax, ebx, ecx, edx;
+++} Leaf;
+++
+++// Returns the result of a call to the cpuid instruction.
+++Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx);
+++
+++// Returns the eax value of the XCR0 register.
+++uint32_t GetXCR0Eax(void);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d8f2f6a4df8641d3d78f59d2b165f8e26765e2ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,39 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// An interface for the filesystem that allows mocking the filesystem in
+++// unittests.
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
+++
+++#include <stddef.h>
+++#include <stdint.h>
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++// Same as linux "open(filename, O_RDONLY)", retries automatically on EINTR.
+++int CpuFeatures_OpenFile(const char* filename);
+++
+++// Same as linux "read(file_descriptor, buffer, buffer_size)", retries
+++// automatically on EINTR.
+++int CpuFeatures_ReadFile(int file_descriptor, void* buffer, size_t buffer_size);
+++
+++// Same as linux "close(file_descriptor)".
+++void CpuFeatures_CloseFile(int file_descriptor);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..62037c8ff3fb7ed69f89b9f911e27ab42cc5da19
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,186 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// Interface to retrieve hardware capabilities. It relies on Linux's getauxval
+++// or `/proc/self/auxval` under the hood.
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
+++
+++#include <stdbool.h>
+++#include <stdint.h>
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++// To avoid depending on the linux kernel we reproduce the architecture specific
+++// constants here.
+++
+++// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
+++#define AARCH64_HWCAP_FP (1UL << 0)
+++#define AARCH64_HWCAP_ASIMD (1UL << 1)
+++#define AARCH64_HWCAP_EVTSTRM (1UL << 2)
+++#define AARCH64_HWCAP_AES (1UL << 3)
+++#define AARCH64_HWCAP_PMULL (1UL << 4)
+++#define AARCH64_HWCAP_SHA1 (1UL << 5)
+++#define AARCH64_HWCAP_SHA2 (1UL << 6)
+++#define AARCH64_HWCAP_CRC32 (1UL << 7)
+++#define AARCH64_HWCAP_ATOMICS (1UL << 8)
+++#define AARCH64_HWCAP_FPHP (1UL << 9)
+++#define AARCH64_HWCAP_ASIMDHP (1UL << 10)
+++#define AARCH64_HWCAP_CPUID (1UL << 11)
+++#define AARCH64_HWCAP_ASIMDRDM (1UL << 12)
+++#define AARCH64_HWCAP_JSCVT (1UL << 13)
+++#define AARCH64_HWCAP_FCMA (1UL << 14)
+++#define AARCH64_HWCAP_LRCPC (1UL << 15)
+++#define AARCH64_HWCAP_DCPOP (1UL << 16)
+++#define AARCH64_HWCAP_SHA3 (1UL << 17)
+++#define AARCH64_HWCAP_SM3 (1UL << 18)
+++#define AARCH64_HWCAP_SM4 (1UL << 19)
+++#define AARCH64_HWCAP_ASIMDDP (1UL << 20)
+++#define AARCH64_HWCAP_SHA512 (1UL << 21)
+++#define AARCH64_HWCAP_SVE (1UL << 22)
+++#define AARCH64_HWCAP_ASIMDFHM (1UL << 23)
+++#define AARCH64_HWCAP_DIT (1UL << 24)
+++#define AARCH64_HWCAP_USCAT (1UL << 25)
+++#define AARCH64_HWCAP_ILRCPC (1UL << 26)
+++#define AARCH64_HWCAP_FLAGM (1UL << 27)
+++#define AARCH64_HWCAP_SSBS (1UL << 28)
+++#define AARCH64_HWCAP_SB (1UL << 29)
+++#define AARCH64_HWCAP_PACA (1UL << 30)
+++#define AARCH64_HWCAP_PACG (1UL << 31)
+++
+++#define AARCH64_HWCAP2_DCPODP (1UL << 0)
+++#define AARCH64_HWCAP2_SVE2 (1UL << 1)
+++#define AARCH64_HWCAP2_SVEAES (1UL << 2)
+++#define AARCH64_HWCAP2_SVEPMULL (1UL << 3)
+++#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4)
+++#define AARCH64_HWCAP2_SVESHA3 (1UL << 5)
+++#define AARCH64_HWCAP2_SVESM4 (1UL << 6)
+++#define AARCH64_HWCAP2_FLAGM2 (1UL << 7)
+++#define AARCH64_HWCAP2_FRINT (1UL << 8)
+++#define AARCH64_HWCAP2_SVEI8MM (1UL << 9)
+++#define AARCH64_HWCAP2_SVEF32MM (1UL << 10)
+++#define AARCH64_HWCAP2_SVEF64MM (1UL << 11)
+++#define AARCH64_HWCAP2_SVEBF16 (1UL << 12)
+++#define AARCH64_HWCAP2_I8MM (1UL << 13)
+++#define AARCH64_HWCAP2_BF16 (1UL << 14)
+++#define AARCH64_HWCAP2_DGH (1UL << 15)
+++#define AARCH64_HWCAP2_RNG (1UL << 16)
+++#define AARCH64_HWCAP2_BTI (1UL << 17)
+++
+++// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
+++#define ARM_HWCAP_SWP (1UL << 0)
+++#define ARM_HWCAP_HALF (1UL << 1)
+++#define ARM_HWCAP_THUMB (1UL << 2)
+++#define ARM_HWCAP_26BIT (1UL << 3)
+++#define ARM_HWCAP_FAST_MULT (1UL << 4)
+++#define ARM_HWCAP_FPA (1UL << 5)
+++#define ARM_HWCAP_VFP (1UL << 6)
+++#define ARM_HWCAP_EDSP (1UL << 7)
+++#define ARM_HWCAP_JAVA (1UL << 8)
+++#define ARM_HWCAP_IWMMXT (1UL << 9)
+++#define ARM_HWCAP_CRUNCH (1UL << 10)
+++#define ARM_HWCAP_THUMBEE (1UL << 11)
+++#define ARM_HWCAP_NEON (1UL << 12)
+++#define ARM_HWCAP_VFPV3 (1UL << 13)
+++#define ARM_HWCAP_VFPV3D16 (1UL << 14)
+++#define ARM_HWCAP_TLS (1UL << 15)
+++#define ARM_HWCAP_VFPV4 (1UL << 16)
+++#define ARM_HWCAP_IDIVA (1UL << 17)
+++#define ARM_HWCAP_IDIVT (1UL << 18)
+++#define ARM_HWCAP_VFPD32 (1UL << 19)
+++#define ARM_HWCAP_LPAE (1UL << 20)
+++#define ARM_HWCAP_EVTSTRM (1UL << 21)
+++#define ARM_HWCAP2_AES (1UL << 0)
+++#define ARM_HWCAP2_PMULL (1UL << 1)
+++#define ARM_HWCAP2_SHA1 (1UL << 2)
+++#define ARM_HWCAP2_SHA2 (1UL << 3)
+++#define ARM_HWCAP2_CRC32 (1UL << 4)
+++
+++// http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/hwcap.h
+++#define MIPS_HWCAP_R6 (1UL << 0)
+++#define MIPS_HWCAP_MSA (1UL << 1)
+++#define MIPS_HWCAP_CRC32 (1UL << 2)
+++
+++// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h
+++#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H
+++/* in AT_HWCAP */
+++#define PPC_FEATURE_32 0x80000000
+++#define PPC_FEATURE_64 0x40000000
+++#define PPC_FEATURE_601_INSTR 0x20000000
+++#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+++#define PPC_FEATURE_HAS_FPU 0x08000000
+++#define PPC_FEATURE_HAS_MMU 0x04000000
+++#define PPC_FEATURE_HAS_4xxMAC 0x02000000
+++#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
+++#define PPC_FEATURE_HAS_SPE 0x00800000
+++#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
+++#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
+++#define PPC_FEATURE_NO_TB 0x00100000
+++#define PPC_FEATURE_POWER4 0x00080000
+++#define PPC_FEATURE_POWER5 0x00040000
+++#define PPC_FEATURE_POWER5_PLUS 0x00020000
+++#define PPC_FEATURE_CELL 0x00010000
+++#define PPC_FEATURE_BOOKE 0x00008000
+++#define PPC_FEATURE_SMT 0x00004000
+++#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
+++#define PPC_FEATURE_ARCH_2_05 0x00001000
+++#define PPC_FEATURE_PA6T 0x00000800
+++#define PPC_FEATURE_HAS_DFP 0x00000400
+++#define PPC_FEATURE_POWER6_EXT 0x00000200
+++#define PPC_FEATURE_ARCH_2_06 0x00000100
+++#define PPC_FEATURE_HAS_VSX 0x00000080
+++
+++#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040
+++
+++/* Reserved - do not use                0x00000004 */
+++#define PPC_FEATURE_TRUE_LE 0x00000002
+++#define PPC_FEATURE_PPC_LE 0x00000001
+++
+++/* in AT_HWCAP2 */
+++#define PPC_FEATURE2_ARCH_2_07 0x80000000
+++#define PPC_FEATURE2_HTM 0x40000000
+++#define PPC_FEATURE2_DSCR 0x20000000
+++#define PPC_FEATURE2_EBB 0x10000000
+++#define PPC_FEATURE2_ISEL 0x08000000
+++#define PPC_FEATURE2_TAR 0x04000000
+++#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
+++#define PPC_FEATURE2_HTM_NOSC 0x01000000
+++#define PPC_FEATURE2_ARCH_3_00 0x00800000
+++#define PPC_FEATURE2_HAS_IEEE128 0x00400000
+++#define PPC_FEATURE2_DARN 0x00200000
+++#define PPC_FEATURE2_SCV 0x00100000
+++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
+++#endif
+++
+++typedef struct {
+++  unsigned long hwcaps;
+++  unsigned long hwcaps2;
+++} HardwareCapabilities;
+++
+++HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+++bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+++                             const HardwareCapabilities hwcaps);
+++
+++typedef struct {
+++  char platform[64];       // 0 terminated string
+++  char base_platform[64];  // 0 terminated string
+++} PlatformType;
+++
+++PlatformType CpuFeatures_GetPlatformType(void);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..39c1b8bace6ce2985eacfb265832c8c57c6d8004
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,49 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// Reads a file line by line and stores the data on the stack. This allows
+++// parsing files in one go without allocating.
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
+++
+++#include <stdbool.h>
+++
+++#include "cpu_features_macros.h"
+++#include "internal/string_view.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  char buffer[STACK_LINE_READER_BUFFER_SIZE];
+++  StringView view;
+++  int fd;
+++  bool skip_mode;
+++} StackLineReader;
+++
+++// Initializes a StackLineReader.
+++void StackLineReader_Initialize(StackLineReader* reader, int fd);
+++
+++typedef struct {
+++  StringView line;  // A view of the line.
+++  bool eof;         // Nothing more to read, we reached EOF.
+++  bool full_line;   // If false the line was truncated to
+++                    // STACK_LINE_READER_BUFFER_SIZE.
+++} LineResult;
+++
+++// Reads the file pointed to by fd and tries to read a full line.
+++LineResult StackLineReader_NextLine(StackLineReader* reader);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..64fed40f3ed00d1f4aab59fc8df9972638cef7ec
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,109 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// A view over a piece of string. The view is not 0 terminated.
+++#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
+++#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
+++
+++#include <stdbool.h>
+++#include <stddef.h>
+++#include <string.h>
+++
+++#include "cpu_features_macros.h"
+++
+++CPU_FEATURES_START_CPP_NAMESPACE
+++
+++typedef struct {
+++  const char* ptr;
+++  size_t size;
+++} StringView;
+++
+++#ifdef __cplusplus
+++static const StringView kEmptyStringView = {NULL, 0};
+++#else
+++static const StringView kEmptyStringView;
+++#endif
+++
+++// Returns a StringView from the provided string.
+++// Passing NULL is valid only if size is 0.
+++static inline StringView view(const char* str, const size_t size) {
+++  StringView view;
+++  view.ptr = str;
+++  view.size = size;
+++  return view;
+++}
+++
+++static inline StringView str(const char* str) { return view(str, strlen(str)); }
+++
+++// Returns the index of the first occurrence of c in view or -1 if not found.
+++int CpuFeatures_StringView_IndexOfChar(const StringView view, char c);
+++
+++// Returns the index of the first occurrence of sub_view in view or -1 if not
+++// found.
+++int CpuFeatures_StringView_IndexOf(const StringView view,
+++                                   const StringView sub_view);
+++
+++// Returns whether a is equal to b (same content).
+++bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b);
+++
+++// Returns whether a starts with b.
+++bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b);
+++
+++// Removes count characters from the beginning of view or kEmptyStringView if
+++// count if greater than view.size.
+++StringView CpuFeatures_StringView_PopFront(const StringView str_view,
+++                                           size_t count);
+++
+++// Removes count characters from the end of view or kEmptyStringView if count if
+++// greater than view.size.
+++StringView CpuFeatures_StringView_PopBack(const StringView str_view,
+++                                          size_t count);
+++
+++// Keeps the count first characters of view or view if count if greater than
+++// view.size.
+++StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
+++                                            size_t count);
+++
+++// Retrieves the first character of view. If view is empty the behavior is
+++// undefined.
+++char CpuFeatures_StringView_Front(const StringView view);
+++
+++// Retrieves the last character of view. If view is empty the behavior is
+++// undefined.
+++char CpuFeatures_StringView_Back(const StringView view);
+++
+++// Removes leading and tailing space characters.
+++StringView CpuFeatures_StringView_TrimWhitespace(StringView view);
+++
+++// Convert StringView to positive integer. e.g. "42", "0x2a".
+++// Returns -1 on error.
+++int CpuFeatures_StringView_ParsePositiveNumber(const StringView view);
+++
+++// Copies src StringView to dst buffer.
+++void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
+++                                       size_t dst_size);
+++
+++// Checks if line contains the specified whitespace separated word.
+++bool CpuFeatures_StringView_HasWord(const StringView line,
+++                                    const char* const word);
+++
+++// Get key/value from line. key and value are separated by ": ".
+++// key and value are cleaned up from leading and trailing whitespaces.
+++bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
+++                                                 StringView* key,
+++                                                 StringView* value);
+++
+++CPU_FEATURES_END_CPP_NAMESPACE
+++
+++#endif  // CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..186708a3fb0232c0da940bdacf589a11874a7ff8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,60 @@@@
+++
+++#
+++# library : NDK compat
+++#
+++find_package(Threads REQUIRED)
+++set (NDK_COMPAT_HDRS cpu-features.h)
+++set (NDK_COMPAT_SRCS
+++  cpu-features.c
+++  $<TARGET_OBJECTS:utils>
+++  $<TARGET_OBJECTS:unix_based_hardware_detection>
+++)
+++# Note that following `add_cpu_features_headers_and_sources` will use
+++# NDK_COMPAT_SRCS in lieu of NDK_COMPAT_HDRS because we don't want cpu_features
+++# headers to be installed alongside ndk_compat.
+++add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS)
+++add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS})
+++setup_include_and_definitions(ndk_compat)
+++target_include_directories(ndk_compat PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
+++target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+++set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
+++
+++include(GNUInstallDirs)
+++install(TARGETS ndk_compat
+++  EXPORT CpuFeaturesNdkCompatTargets
+++  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ndk_compat
+++  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+++  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+++  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+++)
+++install(EXPORT CpuFeaturesNdkCompatTargets
+++  NAMESPACE CpuFeatures::
+++  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat
+++  COMPONENT Devel
+++)
+++include(CMakePackageConfigHelpers)
+++configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/CpuFeaturesNdkCompatConfig.cmake.in
+++  "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake"
+++  INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat"
+++  NO_SET_AND_CHECK_MACRO
+++  NO_CHECK_REQUIRED_COMPONENTS_MACRO
+++)
+++write_basic_package_version_file(
+++  "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake"
+++  COMPATIBILITY SameMajorVersion
+++)
+++install(
+++  FILES
+++    "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake"
+++    "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake"
+++  DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat"
+++  COMPONENT Devel
+++)
+++
+++#
+++# program : NDK compat test program
+++#
+++if(ENABLE_TESTING)
+++  add_executable(ndk-compat-test ndk-compat-test.c)
+++  target_link_libraries(ndk-compat-test PRIVATE ndk_compat)
+++endif()
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..38c83937f93d187f418c7c8e395a4773494331ef
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,4 @@@@
+++Provides a header compatible with [android's NDK cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h).
+++
+++It is intended to be a drop in replacement for this header and help users
+++transition from the NDK to [Google's cpu_features library](https://github.com/google/cpu_features).
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..27ff7bbdfd80d27a15bd31150ae3be933edc1afd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,205 @@@@
+++#include "cpu-features.h"
+++
+++#include <pthread.h>
+++
+++#include "cpu_features_macros.h"
+++#include "internal/filesystem.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++#if defined(CPU_FEATURES_ARCH_ARM)
+++#include "cpuinfo_arm.h"
+++#elif defined(CPU_FEATURES_ARCH_X86)
+++#include "cpuinfo_x86.h"
+++#elif defined(CPU_FEATURES_ARCH_MIPS)
+++#include "cpuinfo_mips.h"
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++#include "cpuinfo_aarch64.h"
+++#endif
+++
+++static pthread_once_t g_once;
+++static int g_inited;
+++static uint64_t g_cpuFeatures;
+++static int g_cpuCount;
+++
+++#ifdef CPU_FEATURES_ARCH_ARM
+++static uint32_t g_cpuIdArm;
+++#endif
+++
+++static void set_cpu_mask_bit(uint32_t index, uint32_t* cpu_mask) {
+++  *cpu_mask |= 1UL << index;
+++}
+++
+++// Examples of valid inputs: "31", "4-31"
+++static void parse_cpu_mask(const StringView text, uint32_t* cpu_mask) {
+++  int separator_index = CpuFeatures_StringView_IndexOfChar(text, '-');
+++  if (separator_index < 0) {  // A single cpu index
+++    int cpu_index = CpuFeatures_StringView_ParsePositiveNumber(text);
+++    if (cpu_index < 0) return;
+++    set_cpu_mask_bit(cpu_index, cpu_mask);
+++  } else {
+++    int cpu_index_a = CpuFeatures_StringView_ParsePositiveNumber(
+++        CpuFeatures_StringView_KeepFront(text, separator_index));
+++    int cpu_index_b = CpuFeatures_StringView_ParsePositiveNumber(
+++        CpuFeatures_StringView_PopFront(text, separator_index + 1));
+++    int i;
+++    if (cpu_index_a < 0 || cpu_index_b < 0) return;
+++    for (i = cpu_index_a; i <= cpu_index_b; ++i) {
+++      if (i < 32) {
+++        set_cpu_mask_bit(i, cpu_mask);
+++      }
+++    }
+++  }
+++}
+++
+++// Format specification from
+++// https://www.kernel.org/doc/Documentation/cputopology.txt
+++// Examples of valid inputs: "31", "2,4-31,32-63", "0-1,3"
+++static void parse_cpu_mask_line(const LineResult result, uint32_t* cpu_mask) {
+++  if (!result.full_line || result.eof) return;
+++  StringView line = result.line;
+++  for (; line.size > 0;) {
+++    int next_entry_index = CpuFeatures_StringView_IndexOfChar(line, ',');
+++    if (next_entry_index < 0) {
+++      parse_cpu_mask(line, cpu_mask);
+++      break;
+++    }
+++    StringView entry = CpuFeatures_StringView_KeepFront(line, next_entry_index);
+++    parse_cpu_mask(entry, cpu_mask);
+++    line = CpuFeatures_StringView_PopFront(line, next_entry_index + 1);
+++  }
+++}
+++
+++static void update_cpu_mask_from_file(const char* filename,
+++                                      uint32_t* cpu_mask) {
+++  const int fd = CpuFeatures_OpenFile(filename);
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    parse_cpu_mask_line(StackLineReader_NextLine(&reader), cpu_mask);
+++    CpuFeatures_CloseFile(fd);
+++  }
+++}
+++
+++static int get_cpu_count(void) {
+++  uint32_t cpu_mask = 0;
+++  update_cpu_mask_from_file("/sys/devices/system/cpu/present", &cpu_mask);
+++  update_cpu_mask_from_file("/sys/devices/system/cpu/possible", &cpu_mask);
+++  return __builtin_popcount(cpu_mask);
+++}
+++
+++static void android_cpuInit(void) {
+++  g_cpuFeatures = 0;
+++  g_cpuCount = 1;
+++  g_inited = 1;
+++
+++  g_cpuCount = get_cpu_count();
+++  if (g_cpuCount == 0) {
+++    g_cpuCount = 1;
+++  }
+++#if defined(CPU_FEATURES_ARCH_ARM)
+++  ArmInfo info = GetArmInfo();
+++  if (info.architecture == 7) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
+++  if (info.features.vfpv3) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+++  if (info.features.neon) {
+++    g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON;
+++    g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_D32;
+++  }
+++  if (info.features.vfpv3d16) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FP16;
+++  if (info.features.idiva) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+++  if (info.features.idivt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
+++  if (info.features.iwmmxt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+++  if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
+++  if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
+++  if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
+++  if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
+++  if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
+++  if (info.architecture >= 6)
+++    g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
+++  if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+++  if (info.features.vfpv4) {
+++    g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA;
+++    g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
+++  }
+++  g_cpuIdArm = GetArmCpuId(&info);
+++#elif defined(CPU_FEATURES_ARCH_X86)
+++  X86Info info = GetX86Info();
+++  if (info.features.ssse3) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
+++  if (info.features.popcnt) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
+++  if (info.features.movbe) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
+++  if (info.features.sse4_1) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1;
+++  if (info.features.sse4_2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2;
+++  if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI;
+++  if (info.features.avx) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX;
+++  if (info.features.rdrnd) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND;
+++  if (info.features.avx2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2;
+++  if (info.features.sha) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI;
+++#elif defined(CPU_FEATURES_ARCH_MIPS)
+++  MipsInfo info = GetMipsInfo();
+++  if (info.features.r6) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6;
+++  if (info.features.msa) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA;
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++  Aarch64Info info = GetAarch64Info();
+++  if (info.features.fp) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
+++  if (info.features.asimd) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
+++  if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
+++  if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
+++  if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
+++  if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
+++  if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
+++#endif
+++}
+++
+++AndroidCpuFamily android_getCpuFamily(void) {
+++#if defined(CPU_FEATURES_ARCH_ARM)
+++  return ANDROID_CPU_FAMILY_ARM;
+++#elif defined(CPU_FEATURES_ARCH_X86_32)
+++  return ANDROID_CPU_FAMILY_X86;
+++#elif defined(CPU_FEATURES_ARCH_MIPS64)
+++  return ANDROID_CPU_FAMILY_MIPS64;
+++#elif defined(CPU_FEATURES_ARCH_MIPS32)
+++  return ANDROID_CPU_FAMILY_MIPS;
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++  return ANDROID_CPU_FAMILY_ARM64;
+++#elif defined(CPU_FEATURES_ARCH_X86_64)
+++  return ANDROID_CPU_FAMILY_X86_64;
+++#else
+++  return ANDROID_CPU_FAMILY_UNKNOWN;
+++#endif
+++}
+++
+++uint64_t android_getCpuFeatures(void) {
+++  pthread_once(&g_once, android_cpuInit);
+++  return g_cpuFeatures;
+++}
+++
+++int android_getCpuCount(void) {
+++  pthread_once(&g_once, android_cpuInit);
+++  return g_cpuCount;
+++}
+++
+++static void android_cpuInitDummy(void) { g_inited = 1; }
+++
+++int android_setCpu(int cpu_count, uint64_t cpu_features) {
+++  /* Fail if the library was already initialized. */
+++  if (g_inited) return 0;
+++  g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
+++  g_cpuFeatures = cpu_features;
+++  pthread_once(&g_once, android_cpuInitDummy);
+++  return 1;
+++}
+++
+++#ifdef CPU_FEATURES_ARCH_ARM
+++
+++uint32_t android_getCpuIdArm(void) {
+++  pthread_once(&g_once, android_cpuInit);
+++  return g_cpuIdArm;
+++}
+++
+++int android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) {
+++  if (!android_setCpu(cpu_count, cpu_features)) return 0;
+++  g_cpuIdArm = cpu_id;
+++  return 1;
+++}
+++
+++#endif  // CPU_FEATURES_ARCH_ARM
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..51bea5387962a0f3abdac9700bd0691989ffbc5d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,320 @@@@
+++/*
+++ * Copyright (C) 2010 The Android Open Source Project
+++ * All rights reserved.
+++ *
+++ * Redistribution and use in source and binary forms, with or without
+++ * modification, are permitted provided that the following conditions
+++ * are met:
+++ *  * Redistributions of source code must retain the above copyright
+++ *    notice, this list of conditions and the following disclaimer.
+++ *  * Redistributions in binary form must reproduce the above copyright
+++ *    notice, this list of conditions and the following disclaimer in
+++ *    the documentation and/or other materials provided with the
+++ *    distribution.
+++ *
+++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+++ * SUCH DAMAGE.
+++ */
+++#ifndef GOOGLE_CPU_FEATURES_H
+++#define GOOGLE_CPU_FEATURES_H
+++#include <stdint.h>
+++#include <sys/cdefs.h>
+++
+++__BEGIN_DECLS
+++
+++/* A list of valid values returned by android_getCpuFamily().
+++ * They describe the CPU Architecture of the current process.
+++ */
+++typedef enum {
+++  ANDROID_CPU_FAMILY_UNKNOWN = 0,
+++  ANDROID_CPU_FAMILY_ARM,
+++  ANDROID_CPU_FAMILY_X86,
+++  ANDROID_CPU_FAMILY_MIPS,
+++  ANDROID_CPU_FAMILY_ARM64,
+++  ANDROID_CPU_FAMILY_X86_64,
+++  ANDROID_CPU_FAMILY_MIPS64,
+++  ANDROID_CPU_FAMILY_MAX /* do not remove */
+++} AndroidCpuFamily;
+++
+++/* Return the CPU family of the current process.
+++ *
+++ * Note that this matches the bitness of the current process. I.e. when
+++ * running a 32-bit binary on a 64-bit capable CPU, this will return the
+++ * 32-bit CPU family value.
+++ */
+++extern AndroidCpuFamily android_getCpuFamily(void);
+++
+++/* Return a bitmap describing a set of optional CPU features that are
+++ * supported by the current device's CPU. The exact bit-flags returned
+++ * depend on the value returned by android_getCpuFamily(). See the
+++ * documentation for the ANDROID_CPU_*_FEATURE_* flags below for details.
+++ */
+++extern uint64_t android_getCpuFeatures(void);
+++
+++/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be
+++ * recognized by the library (see note below for 64-bit ARM). Value details
+++ * are:
+++ *
+++ *   VFPv2:
+++ *     CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs
+++ *     support these instructions. VFPv2 is a subset of VFPv3 so this will
+++ *     be set whenever VFPv3 is set too.
+++ *
+++ *   ARMv7:
+++ *     CPU supports the ARMv7-A basic instruction set.
+++ *     This feature is mandated by the 'armeabi-v7a' ABI.
+++ *
+++ *   VFPv3:
+++ *     CPU supports the VFPv3-D16 instruction set, providing hardware FPU
+++ *     support for single and double precision floating point registers.
+++ *     Note that only 16 FPU registers are available by default, unless
+++ *     the D32 bit is set too. This feature is also mandated by the
+++ *     'armeabi-v7a' ABI.
+++ *
+++ *   VFP_D32:
+++ *     CPU VFP optional extension that provides 32 FPU registers,
+++ *     instead of 16. Note that ARM mandates this feature is the 'NEON'
+++ *     feature is implemented by the CPU.
+++ *
+++ *   NEON:
+++ *     CPU FPU supports "ARM Advanced SIMD" instructions, also known as
+++ *     NEON. Note that this mandates the VFP_D32 feature as well, per the
+++ *     ARM Architecture specification.
+++ *
+++ *   VFP_FP16:
+++ *     Half-width floating precision VFP extension. If set, the CPU
+++ *     supports instructions to perform floating-point operations on
+++ *     16-bit registers. This is part of the VFPv4 specification, but
+++ *     not mandated by any Android ABI.
+++ *
+++ *   VFP_FMA:
+++ *     Fused multiply-accumulate VFP instructions extension. Also part of
+++ *     the VFPv4 specification, but not mandated by any Android ABI.
+++ *
+++ *   NEON_FMA:
+++ *     Fused multiply-accumulate NEON instructions extension. Optional
+++ *     extension from the VFPv4 specification, but not mandated by any
+++ *     Android ABI.
+++ *
+++ *   IDIV_ARM:
+++ *     Integer division available in ARM mode. Only available
+++ *     on recent CPUs (e.g. Cortex-A15).
+++ *
+++ *   IDIV_THUMB2:
+++ *     Integer division available in Thumb-2 mode. Only available
+++ *     on recent CPUs (e.g. Cortex-A15).
+++ *
+++ *   iWMMXt:
+++ *     Optional extension that adds MMX registers and operations to an
+++ *     ARM CPU. This is only available on a few XScale-based CPU designs
+++ *     sold by Marvell. Pretty rare in practice.
+++ *
+++ *   AES:
+++ *     CPU supports AES instructions. These instructions are only
+++ *     available for 32-bit applications running on ARMv8 CPU.
+++ *
+++ *   CRC32:
+++ *     CPU supports CRC32 instructions. These instructions are only
+++ *     available for 32-bit applications running on ARMv8 CPU.
+++ *
+++ *   SHA2:
+++ *     CPU supports SHA2 instructions. These instructions are only
+++ *     available for 32-bit applications running on ARMv8 CPU.
+++ *
+++ *   SHA1:
+++ *     CPU supports SHA1 instructions. These instructions are only
+++ *     available for 32-bit applications running on ARMv8 CPU.
+++ *
+++ *   PMULL:
+++ *     CPU supports 64-bit PMULL and PMULL2 instructions. These
+++ *     instructions are only available for 32-bit applications
+++ *     running on ARMv8 CPU.
+++ *
+++ * If you want to tell the compiler to generate code that targets one of
+++ * the feature set above, you should probably use one of the following
+++ * flags (for more details, see technical note at the end of this file):
+++ *
+++ *   -mfpu=vfp
+++ *   -mfpu=vfpv2
+++ *     These are equivalent and tell GCC to use VFPv2 instructions for
+++ *     floating-point operations. Use this if you want your code to
+++ *     run on *some* ARMv6 devices, and any ARMv7-A device supported
+++ *     by Android.
+++ *
+++ *     Generated code requires VFPv2 feature.
+++ *
+++ *   -mfpu=vfpv3-d16
+++ *     Tell GCC to use VFPv3 instructions (using only 16 FPU registers).
+++ *     This should be generic code that runs on any CPU that supports the
+++ *     'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this.
+++ *
+++ *     Generated code requires VFPv3 feature.
+++ *
+++ *   -mfpu=vfpv3
+++ *     Tell GCC to use VFPv3 instructions with 32 FPU registers.
+++ *     Generated code requires VFPv3|VFP_D32 features.
+++ *
+++ *   -mfpu=neon
+++ *     Tell GCC to use VFPv3 instructions with 32 FPU registers, and
+++ *     also support NEON intrinsics (see <arm_neon.h>).
+++ *     Generated code requires VFPv3|VFP_D32|NEON features.
+++ *
+++ *   -mfpu=vfpv4-d16
+++ *     Generated code requires VFPv3|VFP_FP16|VFP_FMA features.
+++ *
+++ *   -mfpu=vfpv4
+++ *     Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features.
+++ *
+++ *   -mfpu=neon-vfpv4
+++ *     Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA
+++ *     features.
+++ *
+++ *   -mcpu=cortex-a7
+++ *   -mcpu=cortex-a15
+++ *     Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|
+++ *                             NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2
+++ *     This flag implies -mfpu=neon-vfpv4.
+++ *
+++ *   -mcpu=iwmmxt
+++ *     Allows the use of iWMMXt instrinsics with GCC.
+++ *
+++ * IMPORTANT NOTE: These flags should only be tested when
+++ * android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a
+++ * 32-bit process.
+++ *
+++ * When running a 64-bit ARM process on an ARMv8 CPU,
+++ * android_getCpuFeatures() will return a different set of bitflags
+++ */
+++enum {
+++  ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
+++  ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
+++  ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
+++  ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
+++  ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4),
+++  ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5),
+++  ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6),
+++  ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7),
+++  ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8),
+++  ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9),
+++  ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10),
+++  ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11),
+++  ANDROID_CPU_ARM_FEATURE_AES = (1 << 12),
+++  ANDROID_CPU_ARM_FEATURE_PMULL = (1 << 13),
+++  ANDROID_CPU_ARM_FEATURE_SHA1 = (1 << 14),
+++  ANDROID_CPU_ARM_FEATURE_SHA2 = (1 << 15),
+++  ANDROID_CPU_ARM_FEATURE_CRC32 = (1 << 16),
+++};
+++
+++/* The bit flags corresponding to the output of android_getCpuFeatures()
+++ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details
+++ * are:
+++ *
+++ *   FP:
+++ *     CPU has Floating-point unit.
+++ *
+++ *   ASIMD:
+++ *     CPU has Advanced SIMD unit.
+++ *
+++ *   AES:
+++ *     CPU supports AES instructions.
+++ *
+++ *   CRC32:
+++ *     CPU supports CRC32 instructions.
+++ *
+++ *   SHA2:
+++ *     CPU supports SHA2 instructions.
+++ *
+++ *   SHA1:
+++ *     CPU supports SHA1 instructions.
+++ *
+++ *   PMULL:
+++ *     CPU supports 64-bit PMULL and PMULL2 instructions.
+++ */
+++enum {
+++  ANDROID_CPU_ARM64_FEATURE_FP = (1 << 0),
+++  ANDROID_CPU_ARM64_FEATURE_ASIMD = (1 << 1),
+++  ANDROID_CPU_ARM64_FEATURE_AES = (1 << 2),
+++  ANDROID_CPU_ARM64_FEATURE_PMULL = (1 << 3),
+++  ANDROID_CPU_ARM64_FEATURE_SHA1 = (1 << 4),
+++  ANDROID_CPU_ARM64_FEATURE_SHA2 = (1 << 5),
+++  ANDROID_CPU_ARM64_FEATURE_CRC32 = (1 << 6),
+++};
+++
+++/* The bit flags corresponding to the output of android_getCpuFeatures()
+++ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86 or
+++ * ANDROID_CPU_FAMILY_X86_64.
+++ */
+++enum {
+++  ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
+++  ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
+++  ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
+++  ANDROID_CPU_X86_FEATURE_SSE4_1 = (1 << 3),
+++  ANDROID_CPU_X86_FEATURE_SSE4_2 = (1 << 4),
+++  ANDROID_CPU_X86_FEATURE_AES_NI = (1 << 5),
+++  ANDROID_CPU_X86_FEATURE_AVX = (1 << 6),
+++  ANDROID_CPU_X86_FEATURE_RDRAND = (1 << 7),
+++  ANDROID_CPU_X86_FEATURE_AVX2 = (1 << 8),
+++  ANDROID_CPU_X86_FEATURE_SHA_NI = (1 << 9),
+++};
+++
+++/* The bit flags corresponding to the output of android_getCpuFeatures()
+++ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_MIPS
+++ * or ANDROID_CPU_FAMILY_MIPS64.  Values are:
+++ *
+++ *   R6:
+++ *     CPU executes MIPS Release 6 instructions natively, and
+++ *     supports obsoleted R1..R5 instructions only via kernel traps.
+++ *
+++ *   MSA:
+++ *     CPU supports Mips SIMD Architecture instructions.
+++ */
+++enum {
+++  ANDROID_CPU_MIPS_FEATURE_R6 = (1 << 0),
+++  ANDROID_CPU_MIPS_FEATURE_MSA = (1 << 1),
+++};
+++
+++/* Return the number of CPU cores detected on this device.
+++ * Please note the current implementation supports up to 32 cpus.
+++ */
+++extern int android_getCpuCount(void);
+++
+++/* The following is used to force the CPU count and features
+++ * mask in sandboxed processes. Under 4.1 and higher, these processes
+++ * cannot access /proc, which is the only way to get information from
+++ * the kernel about the current hardware (at least on ARM).
+++ *
+++ * It _must_ be called only once, and before any android_getCpuXXX
+++ * function, any other case will fail.
+++ *
+++ * This function return 1 on success, and 0 on failure.
+++ */
+++extern int android_setCpu(int cpu_count, uint64_t cpu_features);
+++
+++#ifdef __arm__
+++
+++/* Retrieve the ARM 32-bit CPUID value from the kernel.
+++ * Note that this cannot work on sandboxed processes under 4.1 and
+++ * higher, unless you called android_setCpuArm() before.
+++ */
+++extern uint32_t android_getCpuIdArm(void);
+++
+++/* An ARM-specific variant of android_setCpu() that also allows you
+++ * to set the ARM CPUID field.
+++ */
+++extern int android_setCpuArm(int cpu_count, uint64_t cpu_features,
+++                             uint32_t cpu_id);
+++
+++#endif
+++
+++__END_DECLS
+++#endif /* GOOGLE_CPU_FEATURES_H */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e4005d43a4168df24e49cea7bad3411b4e476315
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,12 @@@@
+++#include <stdio.h>
+++
+++#include "cpu-features.h"
+++
+++int main() {
+++  printf("android_getCpuFamily()=%d\n", android_getCpuFamily());
+++  printf("android_getCpuFeatures()=0x%08llx\n", android_getCpuFeatures());
+++  printf("android_getCpuCount()=%d\n", android_getCpuCount());
+++#ifdef __arm__
+++  printf("android_getCpuIdArm()=0x%04x\n", android_getCpuIdArm());
+++#endif  //__arm__
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fd88d605e29e20949bc5fb504508f1dbc66dc228
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,209 @@@@
+++#!/usr/bin/env bash
+++
+++readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
+++readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.."
+++readonly ARCHIVE_FOLDER=~/cpu_features_archives
+++readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu
+++readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON"
+++
+++function extract() {
+++  case $1 in
+++    *.tar.bz2)   tar xjf "$1"    ;;
+++    *.tar.xz)    tar xJf "$1"    ;;
+++    *.tar.gz)    tar xzf "$1"    ;;
+++    *)
+++      echo "don't know how to extract '$1'..."
+++      exit 1
+++  esac
+++}
+++
+++function unpackifnotexists() {
+++  mkdir -p "${ARCHIVE_FOLDER}"
+++  cd "${ARCHIVE_FOLDER}" || exit
+++  local URL=$1
+++  local RELATIVE_FOLDER=$2
+++  local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}"
+++  if [[  ! -d "${DESTINATION}" ]] ; then
+++    local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///')
+++    test -f "${ARCHIVE_NAME}" || wget -q "${URL}"
+++    extract "${ARCHIVE_NAME}"
+++    rm -f "${ARCHIVE_NAME}"
+++  fi
+++}
+++
+++function installqemuifneeded() {
+++  local VERSION=${QEMU_VERSION:=2.11.1}
+++  local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el}
+++  local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')}
+++
+++  if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then
+++    echo "qemu ${VERSION} up to date!"
+++    return 0
+++  fi
+++
+++  echo "VERSION: ${VERSION}"
+++  echo "TARGETS: ${TARGETS}"
+++
+++  rm -rf ${QEMU_INSTALL}
+++
+++  # Checking for a tarball before downloading makes testing easier :-)
+++  local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz"
+++  local QEMU_FOLDER="qemu-${VERSION}"
+++  unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER}
+++  cd ${QEMU_FOLDER} || exit
+++
+++  ./configure \
+++    --prefix="${QEMU_INSTALL}" \
+++    --target-list="${TARGETS}" \
+++    --disable-docs \
+++    --disable-sdl \
+++    --disable-gtk \
+++    --disable-gnutls \
+++    --disable-gcrypt \
+++    --disable-nettle \
+++    --disable-curses \
+++    --static
+++
+++  make -j4
+++  make install
+++
+++  echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build
+++}
+++
+++function assert_defined(){
+++  local VALUE=${1}
+++  : "${VALUE?"${1} needs to be defined"}"
+++}
+++
+++function integrate() {
+++  cd "${PROJECT_FOLDER}"
+++  case "${OS}" in
+++   "Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD"
+++                 CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe"
+++                 DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe
+++                 ;;
+++   *)            CMAKE_BUILD_ARGS="--target all"
+++                 CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test"
+++                 DEMO=${BUILD_DIR}/list_cpu_features
+++                 ;;
+++  esac
+++
+++  # Generating CMake configuration
+++  cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}"
+++
+++  # Building
+++  cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS}
+++
+++  # Running tests if needed
+++  if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
+++    return
+++  fi
+++  RUN_CMD=""
+++  if [[ -n "${QEMU_ARCH}" ]]; then
+++    installqemuifneeded
+++    RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}"
+++  fi
+++  for test_binary in ${CMAKE_TEST_FILES}; do
+++    ${RUN_CMD} ${test_binary}
+++  done
+++  ${RUN_CMD} ${DEMO}
+++}
+++
+++function expand_linaro_config() {
+++  assert_defined TARGET
+++  local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11
+++
+++  local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz
+++  local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}"
+++  unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}"
+++
+++  local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz
+++  local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET}
+++  unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}"
+++
+++  local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER}
+++  local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER}
+++
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET})
+++
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER})
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++)
+++
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY)
+++
+++  QEMU_ARGS+=(-L ${SYSROOT_FOLDER})
+++  QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib)
+++}
+++
+++function expand_codescape_config() {
+++  assert_defined TARGET
+++  local DATE=2017.10-08
+++  local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz
+++  local GCC_URL=${CODESCAPE_URL}
+++  local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}"
+++  unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}"
+++
+++  local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER}
+++  local MIPS_FLAGS=""
+++  local LIBC_FOLDER_SUFFIX=""
+++  local FLAVOUR=""
+++  case "${TARGET}" in
+++    "mips32")    MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;;
+++    "mips32el")  MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;;
+++    "mips64")    MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;;
+++    "mips64el")  MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;;
+++    *)           echo 'unknown mips platform'; exit 1;;
+++  esac
+++
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER})
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET})
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++)
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}")
+++  CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}")
+++
+++  local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR}
+++
+++  # Keeping only the sysroot of interest to save on travis cache.
+++  if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then
+++    for folder in ${GCC_FOLDER}/sysroot/*; do
+++      if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then
+++        rm -rf ${folder}
+++      fi
+++    done
+++  fi
+++
+++  local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX}
+++  QEMU_ARGS+=(-L ${SYSROOT_FOLDER})
+++  QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1)
+++}
+++
+++function expand_environment_and_integrate() {
+++  assert_defined PROJECT_FOLDER
+++  assert_defined TARGET
+++
+++  BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}"
+++  mkdir -p "${BUILD_DIR}"
+++
+++  declare -a CONFIG_NAMES=()
+++  declare -a QEMU_ARGS=()
+++  declare -a CMAKE_ADDITIONAL_ARGS=()
+++
+++  case ${TOOLCHAIN} in
+++    LINARO)    expand_linaro_config     ;;
+++    CODESCAPE) expand_codescape_config  ;;
+++    NATIVE)    QEMU_ARCH=""             ;;
+++    *)         echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;;
+++  esac
+++  integrate
+++}
+++
+++if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then
+++  QEMU_ARCHES=${QEMU_ARCH}
+++  expand_environment_and_integrate
+++fi
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d1c61b02e6ff2e9bc3c4d4ed2449d3a1d164ebd1
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,106 @@@@
+++#!/usr/bin/env bash
+++
+++source "$(dirname -- "$0")"/run_integration.sh
+++
+++# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
+++function set_aarch64-linux-gnu() {
+++  TOOLCHAIN=LINARO
+++  TARGET=aarch64-linux-gnu
+++  QEMU_ARCH=aarch64
+++}
+++
+++# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++function set_arm-linux-gnueabihf() {
+++  TOOLCHAIN=LINARO
+++  TARGET=arm-linux-gnueabihf
+++  QEMU_ARCH=arm
+++}
+++
+++# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems
+++function set_armv8l-linux-gnueabihf() {
+++  TOOLCHAIN=LINARO
+++  TARGET=armv8l-linux-gnueabihf
+++  QEMU_ARCH=arm
+++}
+++
+++# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++function set_arm-linux-gnueabi() {
+++  TOOLCHAIN=LINARO
+++  TARGET=arm-linux-gnueabi
+++  QEMU_ARCH=arm
+++}
+++
+++# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems
+++function set_aarch64_be-linux-gnu() {
+++  TOOLCHAIN=LINARO
+++  TARGET=aarch64_be-linux-gnu
+++  QEMU_ARCH=DISABLED
+++}
+++
+++# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++function set_armeb-linux-gnueabihf() {
+++  TOOLCHAIN=LINARO
+++  TARGET=armeb-linux-gnueabihf
+++  QEMU_ARCH=DISABLED
+++}
+++
+++# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
+++function set_armeb-linux-gnueabi() {
+++  TOOLCHAIN=LINARO
+++  TARGET=armeb-linux-gnueabi
+++  QEMU_ARCH=DISABLED
+++}
+++
+++function set_mips32() {
+++  TOOLCHAIN=CODESCAPE
+++  TARGET=mips32
+++  QEMU_ARCH=mips
+++}
+++
+++function set_mips32el() {
+++  TOOLCHAIN=CODESCAPE
+++  TARGET=mips32el
+++  QEMU_ARCH=mipsel
+++}
+++
+++function set_mips64() {
+++  TOOLCHAIN=CODESCAPE
+++  TARGET=mips64
+++  QEMU_ARCH=mips64
+++}
+++
+++function set_mips64el() {
+++  TOOLCHAIN=CODESCAPE
+++  TARGET=mips64el
+++  QEMU_ARCH=mips64el
+++}
+++
+++function set_native() {
+++  TOOLCHAIN=NATIVE
+++  TARGET=native
+++  QEMU_ARCH=""
+++}
+++
+++ENVIRONMENTS="
+++  set_aarch64-linux-gnu
+++  set_arm-linux-gnueabihf
+++  set_armv8l-linux-gnueabihf
+++  set_arm-linux-gnueabi
+++  set_aarch64_be-linux-gnu
+++  set_armeb-linux-gnueabihf
+++  set_armeb-linux-gnueabi
+++  set_mips32
+++  set_mips32el
+++  set_mips64
+++  set_mips64el
+++  set_native
+++"
+++
+++set -e
+++
+++CMAKE_GENERATOR="Ninja"
+++
+++for SET_ENVIRONMENT in ${ENVIRONMENTS}; do
+++  ${SET_ENVIRONMENT}
+++  expand_environment_and_integrate
+++done
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0a5271890a4a1ccde97d7c576d0d58066158ebfb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,150 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_aarch64.h"
+++
+++#include <assert.h>
+++#include <ctype.h>
+++
+++#include "internal/filesystem.h"
+++#include "internal/hwcaps.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++// Generation of feature's getters/setters functions and kGetters, kSetters,
+++// kCpuInfoFlags and kHardwareCapabilities global tables.
+++#define DEFINE_TABLE_FEATURES                                                 \
+++  FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0)                          \
+++  FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0)              \
+++  FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0)      \
+++  FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0)                      \
+++  FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0)              \
+++  FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0)                  \
+++  FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0)                  \
+++  FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0)              \
+++  FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0)      \
+++  FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0)                  \
+++  FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0)      \
+++  FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0)              \
+++  FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0)  \
+++  FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0)              \
+++  FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0)                  \
+++  FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0)              \
+++  FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0)              \
+++  FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0)                  \
+++  FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0)                      \
+++  FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0)                      \
+++  FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0)      \
+++  FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0)          \
+++  FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0)                      \
+++  FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0)  \
+++  FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0)                      \
+++  FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0)              \
+++  FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0)          \
+++  FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0)              \
+++  FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0)                  \
+++  FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0)                          \
+++  FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0)                  \
+++  FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0)                  \
+++  FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP)         \
+++  FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2)                 \
+++  FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES)         \
+++  FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
+++  FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0,                    \
+++          AARCH64_HWCAP2_SVEBITPERM)                                          \
+++  FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3)     \
+++  FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4)         \
+++  FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2)         \
+++  FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT)             \
+++  FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM)     \
+++  FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
+++  FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
+++  FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16)     \
+++  FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM)                 \
+++  FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16)                 \
+++  FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH)                     \
+++  FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG)                     \
+++  FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
+++#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
+++#include "define_tables.h"
+++
+++static bool HandleAarch64Line(const LineResult result,
+++                              Aarch64Info* const info) {
+++  StringView line = result.line;
+++  StringView key, value;
+++  if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+++    if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
+++      for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+++        kSetters[i](&info->features,
+++                    CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+++      }
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
+++      info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
+++      info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
+++      info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
+++      info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    }
+++  }
+++  return !result.eof;
+++}
+++
+++static void FillProcCpuInfoData(Aarch64Info* const info) {
+++  const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    for (;;) {
+++      if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
+++        break;
+++      }
+++    }
+++    CpuFeatures_CloseFile(fd);
+++  }
+++}
+++
+++static const Aarch64Info kEmptyAarch64Info;
+++
+++Aarch64Info GetAarch64Info(void) {
+++  // capabilities are fetched from both getauxval and /proc/cpuinfo so we can
+++  // have some information if the executable is sandboxed (aka no access to
+++  // /proc/cpuinfo).
+++  Aarch64Info info = kEmptyAarch64Info;
+++
+++  FillProcCpuInfoData(&info);
+++  const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+++  for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+++    if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+++      kSetters[i](&info.features, true);
+++    }
+++  }
+++
+++  return info;
+++}
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
+++                                Aarch64FeaturesEnum value) {
+++  if (value >= AARCH64_LAST_) return false;
+++  return kGetters[value](features);
+++}
+++
+++const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
+++  if (value >= AARCH64_LAST_) return "unknown feature";
+++  return kCpuInfoFlags[value];
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0f216bf93adf35888c505ed1bf244a3928c220b0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,212 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_arm.h"
+++
+++#include <assert.h>
+++#include <ctype.h>
+++
+++#include "internal/bit_utils.h"
+++#include "internal/filesystem.h"
+++#include "internal/hwcaps.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++// Generation of feature's getters/setters functions and kGetters, kSetters,
+++// kCpuInfoFlags and kHardwareCapabilities global tables.
+++#define DEFINE_TABLE_FEATURES                                         \
+++  FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0)                      \
+++  FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0)                  \
+++  FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0)              \
+++  FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0)             \
+++  FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
+++  FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0)                      \
+++  FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0)                      \
+++  FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0)                  \
+++  FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0)                  \
+++  FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0)          \
+++  FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0)          \
+++  FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0)      \
+++  FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0)                  \
+++  FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0)              \
+++  FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0)  \
+++  FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0)                      \
+++  FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0)              \
+++  FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0)              \
+++  FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0)              \
+++  FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0)          \
+++  FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0)                  \
+++  FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0)      \
+++  FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES)                     \
+++  FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL)             \
+++  FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1)                 \
+++  FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2)                 \
+++  FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
+++#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
+++#include "define_tables.h"
+++
+++typedef struct {
+++  bool processor_reports_armv6;
+++  bool hardware_reports_goldfish;
+++} ProcCpuInfoData;
+++
+++static int IndexOfNonDigit(StringView str) {
+++  size_t index = 0;
+++  while (str.size && isdigit(CpuFeatures_StringView_Front(str))) {
+++    str = CpuFeatures_StringView_PopFront(str, 1);
+++    ++index;
+++  }
+++  return index;
+++}
+++
+++static bool HandleArmLine(const LineResult result, ArmInfo* const info,
+++                          ProcCpuInfoData* const proc_info) {
+++  StringView line = result.line;
+++  StringView key, value;
+++  if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+++    if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
+++      for (size_t i = 0; i < ARM_LAST_; ++i) {
+++        kSetters[i](&info->features,
+++                    CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+++      }
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
+++      info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
+++      info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
+++      info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
+++      info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("CPU architecture"))) {
+++      // CPU architecture is a number that may be followed by letters. e.g.
+++      // "6TEJ", "7".
+++      const StringView digits =
+++          CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
+++      info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) ||
+++               CpuFeatures_StringView_IsEquals(key, str("model name"))) {
+++      // Android reports this in a non-Linux standard "Processor" but sometimes
+++      // also in "model name", Linux reports it only in "model name"
+++      // see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases
+++      proc_info->processor_reports_armv6 =
+++          CpuFeatures_StringView_IndexOf(value, str("(v6l)")) >= 0;
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("Hardware"))) {
+++      proc_info->hardware_reports_goldfish =
+++          CpuFeatures_StringView_IsEquals(value, str("Goldfish"));
+++    }
+++  }
+++  return !result.eof;
+++}
+++
+++uint32_t GetArmCpuId(const ArmInfo* const info) {
+++  return (ExtractBitRange(info->implementer, 7, 0) << 24) |
+++         (ExtractBitRange(info->variant, 3, 0) << 20) |
+++         (ExtractBitRange(info->part, 11, 0) << 4) |
+++         (ExtractBitRange(info->revision, 3, 0) << 0);
+++}
+++
+++static void FixErrors(ArmInfo* const info,
+++                      ProcCpuInfoData* const proc_cpu_info_data) {
+++  // Fixing Samsung kernel reporting invalid cpu architecture.
+++  // http://code.google.com/p/android/issues/detail?id=10812
+++  if (proc_cpu_info_data->processor_reports_armv6 && info->architecture >= 7) {
+++    info->architecture = 6;
+++  }
+++
+++  // Handle kernel configuration bugs that prevent the correct reporting of CPU
+++  // features.
+++  switch (GetArmCpuId(info)) {
+++    case 0x4100C080:
+++      // Special case: The emulator-specific Android 4.2 kernel fails to report
+++      // support for the 32-bit ARM IDIV instruction. Technically, this is a
+++      // feature of the virtual CPU implemented by the emulator. Note that it
+++      // could also support Thumb IDIV in the future, and this will have to be
+++      // slightly updated.
+++      if (info->architecture >= 7 &&
+++          proc_cpu_info_data->hardware_reports_goldfish) {
+++        info->features.idiva = true;
+++      }
+++      break;
+++    case 0x511004D0:
+++      // https://crbug.com/341598.
+++      info->features.neon = false;
+++      break;
+++    case 0x510006F2:
+++    case 0x510006F3:
+++      // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report
+++      // IDIV support.
+++      info->features.idiva = true;
+++      info->features.idivt = true;
+++      break;
+++  }
+++
+++  // Propagate cpu features.
+++  if (info->features.vfpv4) info->features.vfpv3 = true;
+++  if (info->features.neon) info->features.vfpv3 = true;
+++  if (info->features.vfpv3) info->features.vfp = true;
+++}
+++
+++static void FillProcCpuInfoData(ArmInfo* const info,
+++                                ProcCpuInfoData* proc_cpu_info_data) {
+++  const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    for (;;) {
+++      if (!HandleArmLine(StackLineReader_NextLine(&reader), info,
+++                         proc_cpu_info_data)) {
+++        break;
+++      }
+++    }
+++    CpuFeatures_CloseFile(fd);
+++  }
+++}
+++
+++static const ArmInfo kEmptyArmInfo;
+++
+++static const ProcCpuInfoData kEmptyProcCpuInfoData;
+++
+++ArmInfo GetArmInfo(void) {
+++  // capabilities are fetched from both getauxval and /proc/cpuinfo so we can
+++  // have some information if the executable is sandboxed (aka no access to
+++  // /proc/cpuinfo).
+++  ArmInfo info = kEmptyArmInfo;
+++  ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
+++
+++  FillProcCpuInfoData(&info, &proc_cpu_info_data);
+++  const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+++  for (size_t i = 0; i < ARM_LAST_; ++i) {
+++    if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+++      kSetters[i](&info.features, true);
+++    }
+++  }
+++
+++  FixErrors(&info, &proc_cpu_info_data);
+++
+++  return info;
+++}
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++int GetArmFeaturesEnumValue(const ArmFeatures* features,
+++                            ArmFeaturesEnum value) {
+++  if (value >= ARM_LAST_) return false;
+++  return kGetters[value](features);
+++}
+++
+++const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
+++  if (value >= ARM_LAST_) return "unknown feature";
+++  return kCpuInfoFlags[value];
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..83e959fe94c9382f83053ca26b9e419f33fe37b7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,92 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_mips.h"
+++
+++#include <assert.h>
+++
+++#include "internal/filesystem.h"
+++#include "internal/hwcaps.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++// Generation of feature's getters/setters functions and kGetters, kSetters,
+++// kCpuInfoFlags and kHardwareCapabilities global tables.
+++#define DEFINE_TABLE_FEATURES                      \
+++  FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
+++  FEATURE(MIPS_EVA, eva, "eva", 0, 0)              \
+++  FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
+++#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
+++#include "define_tables.h"
+++
+++static bool HandleMipsLine(const LineResult result,
+++                           MipsFeatures* const features) {
+++  StringView key, value;
+++  // See tests for an example.
+++  if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) {
+++    if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) {
+++      for (size_t i = 0; i < MIPS_LAST_; ++i) {
+++        kSetters[i](features,
+++                    CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+++      }
+++    }
+++  }
+++  return !result.eof;
+++}
+++
+++static void FillProcCpuInfoData(MipsFeatures* const features) {
+++  const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    for (;;) {
+++      if (!HandleMipsLine(StackLineReader_NextLine(&reader), features)) {
+++        break;
+++      }
+++    }
+++    CpuFeatures_CloseFile(fd);
+++  }
+++}
+++
+++static const MipsInfo kEmptyMipsInfo;
+++
+++MipsInfo GetMipsInfo(void) {
+++  // capabilities are fetched from both getauxval and /proc/cpuinfo so we can
+++  // have some information if the executable is sandboxed (aka no access to
+++  // /proc/cpuinfo).
+++  MipsInfo info = kEmptyMipsInfo;
+++
+++  FillProcCpuInfoData(&info.features);
+++  const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+++  for (size_t i = 0; i < MIPS_LAST_; ++i) {
+++    if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+++      kSetters[i](&info.features, true);
+++    }
+++  }
+++  return info;
+++}
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++int GetMipsFeaturesEnumValue(const MipsFeatures* features,
+++                             MipsFeaturesEnum value) {
+++  if (value >= MIPS_LAST_) return false;
+++  return kGetters[value](features);
+++}
+++
+++const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
+++  if (value >= MIPS_LAST_) return "unknown feature";
+++  return kCpuInfoFlags[value];
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..24401f906a8f15b4699c2c9d3cff4e9953bd92dc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,154 @@@@
+++// Copyright 2018 IBM.
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_ppc.h"
+++
+++#include <assert.h>
+++#include <stdbool.h>
+++#include <string.h>
+++
+++#include "internal/bit_utils.h"
+++#include "internal/filesystem.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++// Generation of feature's getters/setters functions and kGetters, kSetters,
+++// kCpuInfoFlags and kHardwareCapabilities global tables.
+++#define DEFINE_TABLE_FEATURES                                                  \
+++  FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0)                           \
+++  FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0)                           \
+++  FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0)           \
+++  FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0)     \
+++  FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0)                     \
+++  FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0)                     \
+++  FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0)        \
+++  FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache",                           \
+++          PPC_FEATURE_UNIFIED_CACHE, 0)                                        \
+++  FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0)                     \
+++  FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle",                          \
+++          PPC_FEATURE_HAS_EFP_SINGLE, 0)                                       \
+++  FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble",                          \
+++          PPC_FEATURE_HAS_EFP_DOUBLE, 0)                                       \
+++  FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0)                      \
+++  FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0)                 \
+++  FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0)                 \
+++  FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0)  \
+++  FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0)                       \
+++  FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0)                     \
+++  FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0)                             \
+++  FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \
+++          0)                                                                   \
+++  FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0)       \
+++  FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0)                         \
+++  FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0)                     \
+++  FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0)     \
+++  FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0)       \
+++  FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0)                     \
+++  FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu",       \
+++          PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0)                               \
+++  FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0)              \
+++  FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0)                   \
+++  FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07)      \
+++  FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM)                            \
+++  FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR)                        \
+++  FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB)                            \
+++  FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL)                        \
+++  FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR)                            \
+++  FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO)      \
+++  FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC)        \
+++  FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00)      \
+++  FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128)    \
+++  FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN)                        \
+++  FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV)                            \
+++  FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0,             \
+++          PPC_FEATURE2_HTM_NO_SUSPEND)
+++#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
+++#include "define_tables.h"
+++
+++static bool HandlePPCLine(const LineResult result,
+++                          PPCPlatformStrings* const strings) {
+++  StringView line = result.line;
+++  StringView key, value;
+++  if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+++    if (CpuFeatures_StringView_HasWord(key, "platform")) {
+++      CpuFeatures_StringView_CopyString(value, strings->platform,
+++                                        sizeof(strings->platform));
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("model"))) {
+++      CpuFeatures_StringView_CopyString(value, strings->model,
+++                                        sizeof(strings->platform));
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("machine"))) {
+++      CpuFeatures_StringView_CopyString(value, strings->machine,
+++                                        sizeof(strings->platform));
+++    } else if (CpuFeatures_StringView_IsEquals(key, str("cpu"))) {
+++      CpuFeatures_StringView_CopyString(value, strings->cpu,
+++                                        sizeof(strings->platform));
+++    }
+++  }
+++  return !result.eof;
+++}
+++
+++static void FillProcCpuInfoData(PPCPlatformStrings* const strings) {
+++  const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    for (;;) {
+++      if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings)) {
+++        break;
+++      }
+++    }
+++    CpuFeatures_CloseFile(fd);
+++  }
+++}
+++
+++static const PPCInfo kEmptyPPCInfo;
+++
+++PPCInfo GetPPCInfo(void) {
+++  /*
+++   * On Power feature flags aren't currently in cpuinfo so we only look at
+++   * the auxilary vector.
+++   */
+++  PPCInfo info = kEmptyPPCInfo;
+++  const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+++  for (size_t i = 0; i < PPC_LAST_; ++i) {
+++    if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+++      kSetters[i](&info.features, true);
+++    }
+++  }
+++  return info;
+++}
+++
+++static const PPCPlatformStrings kEmptyPPCPlatformStrings;
+++
+++PPCPlatformStrings GetPPCPlatformStrings(void) {
+++  PPCPlatformStrings strings = kEmptyPPCPlatformStrings;
+++
+++  FillProcCpuInfoData(&strings);
+++  strings.type = CpuFeatures_GetPlatformType();
+++  return strings;
+++}
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++int GetPPCFeaturesEnumValue(const PPCFeatures* features,
+++                            PPCFeaturesEnum value) {
+++  if (value >= PPC_LAST_) return false;
+++  return kGetters[value](features);
+++}
+++
+++const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
+++  if (value >= PPC_LAST_) return "unknown feature";
+++  return kCpuInfoFlags[value];
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..378ed059ba5b47a0d1097ed6636e51d29fda9a33
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,1622 @@@@
+++// Copyright 2017 Google LLC
+++// Copyright 2020 Intel Corporation
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_x86.h"
+++
+++#include <stdbool.h>
+++#include <string.h>
+++
+++#include "internal/bit_utils.h"
+++#include "internal/cpuid_x86.h"
+++
+++#if !defined(CPU_FEATURES_ARCH_X86)
+++#error "Cannot compile cpuinfo_x86 on a non x86 platform."
+++#endif
+++
+++// Generation of feature's getters/setters functions and kGetters, kSetters,
+++// kCpuInfoFlags global tables.
+++#define DEFINE_TABLE_FEATURES                                                  \
+++  FEATURE(X86_FPU, fpu, "fpu", 0, 0)                                           \
+++  FEATURE(X86_TSC, tsc, "tsc", 0, 0)                                           \
+++  FEATURE(X86_CX8, cx8, "cx8", 0, 0)                                           \
+++  FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0)                                     \
+++  FEATURE(X86_MMX, mmx, "mmx", 0, 0)                                           \
+++  FEATURE(X86_AES, aes, "aes", 0, 0)                                           \
+++  FEATURE(X86_ERMS, erms, "erms", 0, 0)                                        \
+++  FEATURE(X86_F16C, f16c, "f16c", 0, 0)                                        \
+++  FEATURE(X86_FMA4, fma4, "fma4", 0, 0)                                        \
+++  FEATURE(X86_FMA3, fma3, "fma3", 0, 0)                                        \
+++  FEATURE(X86_VAES, vaes, "vaes", 0, 0)                                        \
+++  FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0)                      \
+++  FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0)                                        \
+++  FEATURE(X86_HLE, hle, "hle", 0, 0)                                           \
+++  FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0)                                        \
+++  FEATURE(X86_RTM, rtm, "rtm", 0, 0)                                           \
+++  FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0)                                  \
+++  FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0)                      \
+++  FEATURE(X86_CLWB, clwb, "clwb", 0, 0)                                        \
+++  FEATURE(X86_SSE, sse, "sse", 0, 0)                                           \
+++  FEATURE(X86_SSE2, sse2, "sse2", 0, 0)                                        \
+++  FEATURE(X86_SSE3, sse3, "sse3", 0, 0)                                        \
+++  FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0)                                     \
+++  FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0)                                  \
+++  FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0)                                  \
+++  FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0)                                     \
+++  FEATURE(X86_AVX, avx, "avx", 0, 0)                                           \
+++  FEATURE(X86_AVX2, avx2, "avx2", 0, 0)                                        \
+++  FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0)                               \
+++  FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0)                            \
+++  FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0)                            \
+++  FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0)                            \
+++  FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0)                            \
+++  FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0)                            \
+++  FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0)                            \
+++  FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0)                      \
+++  FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0)                      \
+++  FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0)                   \
+++  FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0)                      \
+++  FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0)                \
+++  FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0)       \
+++  FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0)             \
+++  FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0)             \
+++  FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0) \
+++  FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0)             \
+++  FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0)                   \
+++  FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", \
+++          0, 0)                                                                \
+++  FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0)                            \
+++  FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0)                            \
+++  FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0)                            \
+++  FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0)                         \
+++  FEATURE(X86_SMX, smx, "smx", 0, 0)                                           \
+++  FEATURE(X86_SGX, sgx, "sgx", 0, 0)                                           \
+++  FEATURE(X86_CX16, cx16, "cx16", 0, 0)                                        \
+++  FEATURE(X86_SHA, sha, "sha", 0, 0)                                           \
+++  FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0)                                  \
+++  FEATURE(X86_MOVBE, movbe, "movbe", 0, 0)                                     \
+++  FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0)                                     \
+++  FEATURE(X86_DCA, dca, "dca", 0, 0)                                           \
+++  FEATURE(X86_SS, ss, "ss", 0, 0)
+++#define DEFINE_TABLE_FEATURE_TYPE X86Features
+++#define DEFINE_TABLE_DONT_GENERATE_HWCAPS
+++#include "define_tables.h"
+++
+++// The following includes are necessary to provide SSE detections on pre-AVX
+++// microarchitectures.
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++#include <windows.h>  // IsProcessorFeaturePresent
+++#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+++#include "internal/filesystem.h"         // Needed to parse /proc/cpuinfo
+++#include "internal/stack_line_reader.h"  // Needed to parse /proc/cpuinfo
+++#include "internal/string_view.h"        // Needed to parse /proc/cpuinfo
+++#elif defined(CPU_FEATURES_OS_DARWIN)
+++#if !defined(HAVE_SYSCTLBYNAME)
+++#error "Darwin needs support for sysctlbyname"
+++#endif
+++#include <sys/sysctl.h>
+++#else
+++#error "Unsupported OS"
+++#endif  // CPU_FEATURES_OS
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Definitions for CpuId and GetXCR0Eax.
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+++// Implementation will be provided by test/cpuinfo_x86_test.cc.
+++#elif defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
+++
+++#include <cpuid.h>
+++
+++Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+++  Leaf leaf;
+++  __cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
+++  return leaf;
+++}
+++
+++uint32_t GetXCR0Eax(void) {
+++  uint32_t eax, edx;
+++  /* named form of xgetbv not supported on OSX, so must use byte form, see:
+++     https://github.com/asmjit/asmjit/issues/78
+++   */
+++  __asm(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+++  return eax;
+++}
+++
+++#elif defined(CPU_FEATURES_COMPILER_MSC)
+++
+++#include <immintrin.h>
+++#include <intrin.h>  // For __cpuidex()
+++
+++Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+++  Leaf leaf;
+++  int data[4];
+++  __cpuidex(data, leaf_id, ecx);
+++  leaf.eax = data[0];
+++  leaf.ebx = data[1];
+++  leaf.ecx = data[2];
+++  leaf.edx = data[3];
+++  return leaf;
+++}
+++
+++uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
+++
+++#else
+++#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC."
+++#endif
+++
+++static Leaf CpuId(uint32_t leaf_id) { return GetCpuidLeaf(leaf_id, 0); }
+++
+++static const Leaf kEmptyLeaf;
+++
+++static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) {
+++  if (leaf_id <= max_cpuid_leaf) {
+++    return GetCpuidLeaf(leaf_id, ecx);
+++  } else {
+++    return kEmptyLeaf;
+++  }
+++}
+++
+++static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) {
+++  return SafeCpuIdEx(max_cpuid_leaf, leaf_id, 0);
+++}
+++
+++#define MASK_XMM 0x2
+++#define MASK_YMM 0x4
+++#define MASK_MASKREG 0x20
+++#define MASK_ZMM0_15 0x40
+++#define MASK_ZMM16_31 0x80
+++#define MASK_XTILECFG 0x20000
+++#define MASK_XTILEDATA 0x40000
+++
+++static bool HasMask(uint32_t value, uint32_t mask) {
+++  return (value & mask) == mask;
+++}
+++
+++// Checks that operating system saves and restores xmm registers during context
+++// switches.
+++static bool HasXmmOsXSave(uint32_t xcr0_eax) {
+++  return HasMask(xcr0_eax, MASK_XMM);
+++}
+++
+++// Checks that operating system saves and restores ymm registers during context
+++// switches.
+++static bool HasYmmOsXSave(uint32_t xcr0_eax) {
+++  return HasMask(xcr0_eax, MASK_XMM | MASK_YMM);
+++}
+++
+++// Checks that operating system saves and restores zmm registers during context
+++// switches.
+++static bool HasZmmOsXSave(uint32_t xcr0_eax) {
+++  return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
+++                               MASK_ZMM16_31);
+++}
+++
+++// Checks that operating system saves and restores AMX/TMUL state during context
+++// switches.
+++static bool HasTmmOsXSave(uint32_t xcr0_eax) {
+++  return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
+++                               MASK_ZMM16_31 | MASK_XTILECFG | MASK_XTILEDATA);
+++}
+++
+++static bool HasSecondFMA(uint32_t model) {
+++  // Skylake server
+++  if (model == 0x55) {
+++    char proc_name[49] = {0};
+++    FillX86BrandString(proc_name);
+++    // detect Xeon
+++    if (proc_name[9] == 'X') {
+++      // detect Silver or Bronze
+++      if (proc_name[17] == 'S' || proc_name[17] == 'B') return false;
+++      // detect Gold 5_20 and below, except for Gold 53__
+++      if (proc_name[17] == 'G' && proc_name[22] == '5')
+++        return ((proc_name[23] == '3') ||
+++                (proc_name[24] == '2' && proc_name[25] == '2'));
+++      // detect Xeon W 210x
+++      if (proc_name[17] == 'W' && proc_name[21] == '0') return false;
+++      // detect Xeon D 2xxx
+++      if (proc_name[17] == 'D' && proc_name[19] == '2' && proc_name[20] == '1')
+++        return false;
+++    }
+++    return true;
+++  }
+++  // Cannon Lake client
+++  if (model == 0x66) return false;
+++  // Ice Lake client
+++  if (model == 0x7d || model == 0x7e) return false;
+++  // This is the right default...
+++  return true;
+++}
+++
+++static void SetVendor(const Leaf leaf, char* const vendor) {
+++  *(uint32_t*)(vendor) = leaf.ebx;
+++  *(uint32_t*)(vendor + 4) = leaf.edx;
+++  *(uint32_t*)(vendor + 8) = leaf.ecx;
+++  vendor[12] = '\0';
+++}
+++
+++static int IsVendor(const Leaf leaf, const char* const name) {
+++  const uint32_t ebx = *(const uint32_t*)(name);
+++  const uint32_t edx = *(const uint32_t*)(name + 4);
+++  const uint32_t ecx = *(const uint32_t*)(name + 8);
+++  return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
+++}
+++
+++static const CacheLevelInfo kEmptyCacheLevelInfo;
+++
+++static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
+++  const int UNDEF = -1;
+++  const int KiB = 1024;
+++  const int MiB = 1024 * KiB;
+++  switch (reg) {
+++    case 0x01:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 32,
+++                              .partitioning = 0};
+++    case 0x02:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 2,
+++                              .partitioning = 0};
+++    case 0x03:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0x04:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 8,
+++                              .partitioning = 0};
+++    case 0x05:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 32,
+++                              .partitioning = 0};
+++    case 0x06:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 8 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x08:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x09:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 32 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x0A:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 8 * KiB,
+++                              .ways = 2,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x0B:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 4,
+++                              .partitioning = 0};
+++    case 0x0C:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x0D:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x0E:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 24 * KiB,
+++                              .ways = 6,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x1D:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 128 * KiB,
+++                              .ways = 2,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x21:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 256 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x22:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x23:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x24:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x25:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x29:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x2C:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 32 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x30:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 32 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x40:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = UNDEF,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x41:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 128 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x42:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 256 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x43:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x44:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x45:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x46:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x47:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 8 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x48:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 3 * MiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x49:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case (0x49 | (1 << 8)):
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4A:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 6 * MiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4B:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 8 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4C:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 12 * MiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4D:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 16 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4E:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 6 * MiB,
+++                              .ways = 24,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x4F:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 32,
+++                              .partitioning = 0};
+++    case 0x50:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0x51:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 128,
+++                              .partitioning = 0};
+++    case 0x52:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 256,
+++                              .partitioning = 0};
+++    case 0x55:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 7,
+++                              .partitioning = 0};
+++    case 0x56:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 16,
+++                              .partitioning = 0};
+++    case 0x57:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 16,
+++                              .partitioning = 0};
+++    case 0x59:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 16,
+++                              .partitioning = 0};
+++    case 0x5A:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 32,
+++                              .partitioning = 0};
+++    case 0x5B:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0x5C:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 128,
+++                              .partitioning = 0};
+++    case 0x5D:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 256,
+++                              .partitioning = 0};
+++    case 0x60:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x61:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 48,
+++                              .partitioning = 0};
+++    case 0x63:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 4,
+++                              .partitioning = 0};
+++    case 0x66:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 8 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x67:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x68:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 32 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x70:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 12 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x71:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 16 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x72:
+++      return (CacheLevelInfo){.level = 1,
+++                              .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+++                              .cache_size = 32 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x76:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 8,
+++                              .partitioning = 0};
+++    case 0x78:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x79:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 128 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x7A:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 256 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x7B:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x7C:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 2};
+++    case 0x7D:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x7F:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 2,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x80:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x82:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 256 * KiB,
+++                              .ways = 8,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x83:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 8,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x84:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 8,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x85:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 8,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x86:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 4,
+++                              .line_size = 32,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0x87:
+++      return (CacheLevelInfo){.level = 2,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xA0:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_DTLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 0xFF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 32,
+++                              .partitioning = 0};
+++    case 0xB0:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 128,
+++                              .partitioning = 0};
+++    case 0xB1:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 8,
+++                              .partitioning = 0};
+++    case 0xB2:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0xB3:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 128,
+++                              .partitioning = 0};
+++    case 0xB4:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 256,
+++                              .partitioning = 0};
+++    case 0xB5:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0xB6:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 128,
+++                              .partitioning = 0};
+++    case 0xBA:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 64,
+++                              .partitioning = 0};
+++    case 0xC0:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_TLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 8,
+++                              .partitioning = 0};
+++    case 0xC1:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_STLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 8,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 1024,
+++                              .partitioning = 0};
+++    case 0xC2:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_DTLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 16,
+++                              .partitioning = 0};
+++    case 0xC3:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_STLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 6,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 1536,
+++                              .partitioning = 0};
+++    case 0xCA:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_STLB,
+++                              .cache_size = 4 * KiB,
+++                              .ways = 4,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = 512,
+++                              .partitioning = 0};
+++    case 0xD0:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 512 * KiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xD1:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xD2:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 4,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xD6:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xD7:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xD8:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 8,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xDC:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 1 * 1536 * KiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xDD:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 3 * MiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xDE:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 6 * MiB,
+++                              .ways = 12,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xE2:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 2 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xE3:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 4 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xE4:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 8 * MiB,
+++                              .ways = 16,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xEA:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 12 * MiB,
+++                              .ways = 24,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xEB:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 18 * MiB,
+++                              .ways = 24,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xEC:
+++      return (CacheLevelInfo){.level = 3,
+++                              .cache_type = CPU_FEATURE_CACHE_DATA,
+++                              .cache_size = 24 * MiB,
+++                              .ways = 24,
+++                              .line_size = 64,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xF0:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+++                              .cache_size = 64 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xF1:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+++                              .cache_size = 128 * KiB,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    case 0xFF:
+++      return (CacheLevelInfo){.level = UNDEF,
+++                              .cache_type = CPU_FEATURE_CACHE_NULL,
+++                              .cache_size = UNDEF,
+++                              .ways = UNDEF,
+++                              .line_size = UNDEF,
+++                              .tlb_entries = UNDEF,
+++                              .partitioning = 0};
+++    default:
+++      return kEmptyCacheLevelInfo;
+++  }
+++}
+++
+++static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) {
+++  for (int i = 0; i < 4; ++i) {
+++    result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8);
+++  }
+++}
+++
+++static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
+++  Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
+++  uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
+++  for (int i = 0; i < 4; ++i) {
+++    if (registers[i] & (1U << 31)) {
+++      continue;  // register does not contains valid information
+++    }
+++    uint32_t bytes[4];
+++    GetByteArrayFromRegister(bytes, registers[i]);
+++    for (int j = 0; j < 4; ++j) {
+++      if (bytes[j] == 0xFF)
+++        break;  // leaf 4 should be used to fetch cache information
+++      info->levels[info->size] = GetCacheLevelInfo(bytes[j]);
+++    }
+++    info->size++;
+++  }
+++}
+++
+++static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
+++  info->size = 0;
+++  for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) {
+++    const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id);
+++    CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
+++    if (cache_type == CPU_FEATURE_CACHE_NULL) {
+++      info->levels[cache_id] = kEmptyCacheLevelInfo;
+++      continue;
+++    }
+++    int level = ExtractBitRange(leaf.eax, 7, 5);
+++    int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
+++    int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
+++    int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
+++    int tlb_entries = leaf.ecx + 1;
+++    int cache_size = (ways * partitioning * line_size * (tlb_entries));
+++    info->levels[cache_id] = (CacheLevelInfo){.level = level,
+++                                              .cache_type = cache_type,
+++                                              .cache_size = cache_size,
+++                                              .ways = ways,
+++                                              .line_size = line_size,
+++                                              .tlb_entries = tlb_entries,
+++                                              .partitioning = partitioning};
+++    info->size++;
+++  }
+++}
+++
+++// Internal structure to hold the OS support for vector operations.
+++// Avoid to recompute them since each call to cpuid is ~100 cycles.
+++typedef struct {
+++  bool have_sse_via_os;
+++  bool have_sse_via_cpuid;
+++  bool have_avx;
+++  bool have_avx512;
+++  bool have_amx;
+++} OsSupport;
+++
+++static const OsSupport kEmptyOsSupport;
+++
+++static OsSupport CheckOsSupport(const uint32_t max_cpuid_leaf) {
+++  const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
+++  const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
+++  const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
+++  const bool have_xcr0 = have_xsave && have_osxsave;
+++
+++  OsSupport os_support = kEmptyOsSupport;
+++
+++  if (have_xcr0) {
+++    // AVX capable cpu will expose XCR0.
+++    const uint32_t xcr0_eax = GetXCR0Eax();
+++    os_support.have_sse_via_cpuid = HasXmmOsXSave(xcr0_eax);
+++    os_support.have_avx = HasYmmOsXSave(xcr0_eax);
+++    os_support.have_avx512 = HasZmmOsXSave(xcr0_eax);
+++    os_support.have_amx = HasTmmOsXSave(xcr0_eax);
+++  } else {
+++    // Atom based or older cpus need to ask the OS for sse support.
+++    os_support.have_sse_via_os = true;
+++  }
+++
+++  return os_support;
+++}
+++
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+++extern bool GetWindowsIsProcessorFeaturePresent(DWORD);
+++#else  // CPU_FEATURES_MOCK_CPUID_X86
+++static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+++  return IsProcessorFeaturePresent(ProcessorFeature);
+++}
+++#endif
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+++extern bool GetDarwinSysCtlByName(const char*);
+++#else  // CPU_FEATURES_MOCK_CPUID_X86
+++static bool GetDarwinSysCtlByName(const char* name) {
+++  int enabled;
+++  size_t enabled_len = sizeof(enabled);
+++  const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0);
+++  return failure ? false : enabled;
+++}
+++#endif
+++#endif  // CPU_FEATURES_OS_DARWIN
+++
+++static void DetectSseViaOs(X86Features* features) {
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
+++  features->sse =
+++      GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
+++  features->sse2 =
+++      GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+++  features->sse3 =
+++      GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
+++#elif defined(CPU_FEATURES_OS_DARWIN)
+++  // Handling Darwin platform through sysctlbyname.
+++  features->sse = GetDarwinSysCtlByName("hw.optional.sse");
+++  features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2");
+++  features->sse3 = GetDarwinSysCtlByName("hw.optional.sse3");
+++  features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3");
+++  features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1");
+++  features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2");
+++#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+++  // Handling Linux platform through /proc/cpuinfo.
+++  const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+++  if (fd >= 0) {
+++    StackLineReader reader;
+++    StackLineReader_Initialize(&reader, fd);
+++    for (;;) {
+++      const LineResult result = StackLineReader_NextLine(&reader);
+++      const StringView line = result.line;
+++      StringView key, value;
+++      if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+++        if (CpuFeatures_StringView_IsEquals(key, str("flags"))) {
+++          features->sse = CpuFeatures_StringView_HasWord(value, "sse");
+++          features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2");
+++          features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3");
+++          features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3");
+++          features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1");
+++          features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2");
+++          break;
+++        }
+++      }
+++      if (result.eof) break;
+++    }
+++    CpuFeatures_CloseFile(fd);
+++  }
+++#else
+++#error "Unsupported fallback detection of SSE OS support."
+++#endif
+++}
+++
+++// Reference https://en.wikipedia.org/wiki/CPUID.
+++static void ParseCpuId(const uint32_t max_cpuid_leaf,
+++                       const OsSupport os_support, X86Info* info) {
+++  const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
+++  const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
+++  const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1);
+++
+++  const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
+++  const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
+++  const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4);
+++  const uint32_t extended_model = ExtractBitRange(leaf_1.eax, 19, 16);
+++
+++  X86Features* const features = &info->features;
+++
+++  info->family = extended_family + family;
+++  info->model = (extended_model << 4) + model;
+++  info->stepping = ExtractBitRange(leaf_1.eax, 3, 0);
+++
+++  features->fpu = IsBitSet(leaf_1.edx, 0);
+++  features->tsc = IsBitSet(leaf_1.edx, 4);
+++  features->cx8 = IsBitSet(leaf_1.edx, 8);
+++  features->clfsh = IsBitSet(leaf_1.edx, 19);
+++  features->mmx = IsBitSet(leaf_1.edx, 23);
+++  features->ss = IsBitSet(leaf_1.edx, 27);
+++  features->pclmulqdq = IsBitSet(leaf_1.ecx, 1);
+++  features->smx = IsBitSet(leaf_1.ecx, 6);
+++  features->cx16 = IsBitSet(leaf_1.ecx, 13);
+++  features->dca = IsBitSet(leaf_1.ecx, 18);
+++  features->movbe = IsBitSet(leaf_1.ecx, 22);
+++  features->popcnt = IsBitSet(leaf_1.ecx, 23);
+++  features->aes = IsBitSet(leaf_1.ecx, 25);
+++  features->f16c = IsBitSet(leaf_1.ecx, 29);
+++  features->rdrnd = IsBitSet(leaf_1.ecx, 30);
+++  features->sgx = IsBitSet(leaf_7.ebx, 2);
+++  features->bmi1 = IsBitSet(leaf_7.ebx, 3);
+++  features->hle = IsBitSet(leaf_7.ebx, 4);
+++  features->bmi2 = IsBitSet(leaf_7.ebx, 8);
+++  features->erms = IsBitSet(leaf_7.ebx, 9);
+++  features->rtm = IsBitSet(leaf_7.ebx, 11);
+++  features->rdseed = IsBitSet(leaf_7.ebx, 18);
+++  features->clflushopt = IsBitSet(leaf_7.ebx, 23);
+++  features->clwb = IsBitSet(leaf_7.ebx, 24);
+++  features->sha = IsBitSet(leaf_7.ebx, 29);
+++  features->vaes = IsBitSet(leaf_7.ecx, 9);
+++  features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
+++
+++  if (os_support.have_sse_via_os) {
+++    DetectSseViaOs(features);
+++  } else if (os_support.have_sse_via_cpuid) {
+++    features->sse = IsBitSet(leaf_1.edx, 25);
+++    features->sse2 = IsBitSet(leaf_1.edx, 26);
+++    features->sse3 = IsBitSet(leaf_1.ecx, 0);
+++    features->ssse3 = IsBitSet(leaf_1.ecx, 9);
+++    features->sse4_1 = IsBitSet(leaf_1.ecx, 19);
+++    features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
+++  }
+++
+++  if (os_support.have_avx) {
+++    features->fma3 = IsBitSet(leaf_1.ecx, 12);
+++    features->avx = IsBitSet(leaf_1.ecx, 28);
+++    features->avx2 = IsBitSet(leaf_7.ebx, 5);
+++  }
+++
+++  if (os_support.have_avx512) {
+++    features->avx512f = IsBitSet(leaf_7.ebx, 16);
+++    features->avx512cd = IsBitSet(leaf_7.ebx, 28);
+++    features->avx512er = IsBitSet(leaf_7.ebx, 27);
+++    features->avx512pf = IsBitSet(leaf_7.ebx, 26);
+++    features->avx512bw = IsBitSet(leaf_7.ebx, 30);
+++    features->avx512dq = IsBitSet(leaf_7.ebx, 17);
+++    features->avx512vl = IsBitSet(leaf_7.ebx, 31);
+++    features->avx512ifma = IsBitSet(leaf_7.ebx, 21);
+++    features->avx512vbmi = IsBitSet(leaf_7.ecx, 1);
+++    features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6);
+++    features->avx512vnni = IsBitSet(leaf_7.ecx, 11);
+++    features->avx512bitalg = IsBitSet(leaf_7.ecx, 12);
+++    features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
+++    features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
+++    features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
+++    features->avx512_second_fma = HasSecondFMA(info->model);
+++    features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3);
+++    features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5);
+++    features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8);
+++  }
+++
+++  if (os_support.have_amx) {
+++    features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
+++    features->amx_tile = IsBitSet(leaf_7.edx, 24);
+++    features->amx_int8 = IsBitSet(leaf_7.edx, 25);
+++  }
+++}
+++
+++// Reference
+++// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
+++static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) {
+++  const Leaf leaf_80000000 = CpuId(0x80000000);
+++  const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
+++  const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
+++
+++  X86Features* const features = &info->features;
+++
+++  if (os_support.have_sse_via_cpuid) {
+++    features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
+++  }
+++
+++  if (os_support.have_avx) {
+++    features->fma4 = IsBitSet(leaf_80000001.ecx, 16);
+++  }
+++}
+++
+++static const X86Info kEmptyX86Info;
+++static const CacheInfo kEmptyCacheInfo;
+++
+++X86Info GetX86Info(void) {
+++  X86Info info = kEmptyX86Info;
+++  const Leaf leaf_0 = CpuId(0);
+++  const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
+++  const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
+++  SetVendor(leaf_0, info.vendor);
+++  if (is_intel || is_amd) {
+++    const uint32_t max_cpuid_leaf = leaf_0.eax;
+++    const OsSupport os_support = CheckOsSupport(max_cpuid_leaf);
+++    ParseCpuId(max_cpuid_leaf, os_support, &info);
+++    if (is_amd) {
+++      ParseExtraAMDCpuId(&info, os_support);
+++    }
+++  }
+++  return info;
+++}
+++
+++CacheInfo GetX86CacheInfo(void) {
+++  CacheInfo info = kEmptyCacheInfo;
+++  const Leaf leaf_0 = CpuId(0);
+++  const uint32_t max_cpuid_leaf = leaf_0.eax;
+++  if (IsVendor(leaf_0, "GenuineIntel")) {
+++    ParseLeaf2(max_cpuid_leaf, &info);
+++    ParseLeaf4(max_cpuid_leaf, &info);
+++  }
+++  return info;
+++}
+++
+++#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF))
+++
+++X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
+++  if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) {
+++    switch (CPUID(info->family, info->model)) {
+++      case CPUID(0x06, 0x35):
+++      case CPUID(0x06, 0x36):
+++        // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture)
+++        return INTEL_ATOM_BNL;
+++      case CPUID(0x06, 0x37):
+++      case CPUID(0x06, 0x4C):
+++        // https://en.wikipedia.org/wiki/Silvermont
+++        return INTEL_ATOM_SMT;
+++      case CPUID(0x06, 0x5C):
+++        // https://en.wikipedia.org/wiki/Goldmont
+++        return INTEL_ATOM_GMT;
+++      case CPUID(0x06, 0x0F):
+++      case CPUID(0x06, 0x16):
+++        // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture)
+++        return INTEL_CORE;
+++      case CPUID(0x06, 0x17):
+++      case CPUID(0x06, 0x1D):
+++        // https://en.wikipedia.org/wiki/Penryn_(microarchitecture)
+++        return INTEL_PNR;
+++      case CPUID(0x06, 0x1A):
+++      case CPUID(0x06, 0x1E):
+++      case CPUID(0x06, 0x1F):
+++      case CPUID(0x06, 0x2E):
+++        // https://en.wikipedia.org/wiki/Nehalem_(microarchitecture)
+++        return INTEL_NHM;
+++      case CPUID(0x06, 0x25):
+++      case CPUID(0x06, 0x2C):
+++      case CPUID(0x06, 0x2F):
+++        // https://en.wikipedia.org/wiki/Westmere_(microarchitecture)
+++        return INTEL_WSM;
+++      case CPUID(0x06, 0x2A):
+++      case CPUID(0x06, 0x2D):
+++        // https://en.wikipedia.org/wiki/Sandy_Bridge#Models_and_steppings
+++        return INTEL_SNB;
+++      case CPUID(0x06, 0x3A):
+++      case CPUID(0x06, 0x3E):
+++        // https://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)#Models_and_steppings
+++        return INTEL_IVB;
+++      case CPUID(0x06, 0x3C):
+++      case CPUID(0x06, 0x3F):
+++      case CPUID(0x06, 0x45):
+++      case CPUID(0x06, 0x46):
+++        // https://en.wikipedia.org/wiki/Haswell_(microarchitecture)
+++        return INTEL_HSW;
+++      case CPUID(0x06, 0x3D):
+++      case CPUID(0x06, 0x47):
+++      case CPUID(0x06, 0x4F):
+++      case CPUID(0x06, 0x56):
+++        // https://en.wikipedia.org/wiki/Broadwell_(microarchitecture)
+++        return INTEL_BDW;
+++      case CPUID(0x06, 0x4E):
+++      case CPUID(0x06, 0x55):
+++      case CPUID(0x06, 0x5E):
+++        // https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
+++        return INTEL_SKL;
+++      case CPUID(0x06, 0x66):
+++        // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
+++        return INTEL_CNL;
+++      case CPUID(0x06, 0x7D):  // client
+++      case CPUID(0x06, 0x7E):  // client
+++      case CPUID(0x06, 0x9D):  // NNP-I
+++      case CPUID(0x06, 0x6A):  // server
+++      case CPUID(0x06, 0x6C):  // server
+++        // https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor)
+++        return INTEL_ICL;
+++      case CPUID(0x06, 0x8C):
+++      case CPUID(0x06, 0x8D):
+++        // https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture)
+++        return INTEL_TGL;
+++      case CPUID(0x06, 0x8F):
+++        // https://en.wikipedia.org/wiki/Sapphire_Rapids
+++        return INTEL_SPR;
+++      case CPUID(0x06, 0x8E):
+++        switch (info->stepping) {
+++          case 9:
+++            return INTEL_KBL;  // https://en.wikipedia.org/wiki/Kaby_Lake
+++          case 10:
+++            return INTEL_CFL;  // https://en.wikipedia.org/wiki/Coffee_Lake
+++          case 11:
+++            return INTEL_WHL;  // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture)
+++          default:
+++            return X86_UNKNOWN;
+++        }
+++      case CPUID(0x06, 0x9E):
+++        if (info->stepping > 9) {
+++          // https://en.wikipedia.org/wiki/Coffee_Lake
+++          return INTEL_CFL;
+++        } else {
+++          // https://en.wikipedia.org/wiki/Kaby_Lake
+++          return INTEL_KBL;
+++        }
+++      default:
+++        return X86_UNKNOWN;
+++    }
+++  }
+++  if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) {
+++    switch (info->family) {
+++        // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
+++      case 0x0F:
+++        return AMD_HAMMER;
+++      case 0x10:
+++        return AMD_K10;
+++      case 0x14:
+++        return AMD_BOBCAT;
+++      case 0x15:
+++        return AMD_BULLDOZER;
+++      case 0x16:
+++        return AMD_JAGUAR;
+++      case 0x17:
+++        return AMD_ZEN;
+++      default:
+++        return X86_UNKNOWN;
+++    }
+++  }
+++  return X86_UNKNOWN;
+++}
+++
+++static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id,
+++                      char* buffer) {
+++  const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id);
+++  // We allow calling memcpy from SetString which is only called when requesting
+++  // X86BrandString.
+++  memcpy(buffer, &leaf, sizeof(Leaf));
+++}
+++
+++void FillX86BrandString(char brand_string[49]) {
+++  const Leaf leaf_ext_0 = CpuId(0x80000000);
+++  const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax;
+++  SetString(max_cpuid_leaf_ext, 0x80000002, brand_string);
+++  SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16);
+++  SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32);
+++  brand_string[48] = '\0';
+++}
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Introspection functions
+++
+++int GetX86FeaturesEnumValue(const X86Features* features,
+++                            X86FeaturesEnum value) {
+++  if (value >= X86_LAST_) return false;
+++  return kGetters[value](features);
+++}
+++
+++const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
+++  if (value >= X86_LAST_) return "unknown_feature";
+++  return kCpuInfoFlags[value];
+++}
+++
+++const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
+++  switch (uarch) {
+++    case X86_UNKNOWN:
+++      return "X86_UNKNOWN";
+++    case INTEL_CORE:
+++      return "INTEL_CORE";
+++    case INTEL_PNR:
+++      return "INTEL_PNR";
+++    case INTEL_NHM:
+++      return "INTEL_NHM";
+++    case INTEL_ATOM_BNL:
+++      return "INTEL_ATOM_BNL";
+++    case INTEL_WSM:
+++      return "INTEL_WSM";
+++    case INTEL_SNB:
+++      return "INTEL_SNB";
+++    case INTEL_IVB:
+++      return "INTEL_IVB";
+++    case INTEL_ATOM_SMT:
+++      return "INTEL_ATOM_SMT";
+++    case INTEL_HSW:
+++      return "INTEL_HSW";
+++    case INTEL_BDW:
+++      return "INTEL_BDW";
+++    case INTEL_SKL:
+++      return "INTEL_SKL";
+++    case INTEL_ATOM_GMT:
+++      return "INTEL_ATOM_GMT";
+++    case INTEL_KBL:
+++      return "INTEL_KBL";
+++    case INTEL_CFL:
+++      return "INTEL_CFL";
+++    case INTEL_WHL:
+++      return "INTEL_WHL";
+++    case INTEL_CNL:
+++      return "INTEL_CNL";
+++    case INTEL_ICL:
+++      return "INTEL_ICL";
+++    case INTEL_TGL:
+++      return "INTEL_TGL";
+++    case INTEL_SPR:
+++      return "INTEL_SPR";
+++    case AMD_HAMMER:
+++      return "AMD_HAMMER";
+++    case AMD_K10:
+++      return "AMD_K10";
+++    case AMD_BOBCAT:
+++      return "AMD_BOBCAT";
+++    case AMD_BULLDOZER:
+++      return "AMD_BULLDOZER";
+++    case AMD_JAGUAR:
+++      return "AMD_JAGUAR";
+++    case AMD_ZEN:
+++      return "AMD_ZEN";
+++  }
+++  return "unknown microarchitecture";
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dc1485c476429e917ee8c77bbc18ad37f5916261
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,67 @@@@
+++// Copyright 2020 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// The following preprocessor constants must be defined before including this
+++// file:
+++//  - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
+++//  - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
+++
+++// This file is to be included once per `cpuinfo_XXX.c` in order to construct
+++// feature getters and setters functions as well as several enum indexed tables
+++// from the db file.
+++// - `kGetters` a table of getters function pointers from feature enum to
+++// retrieve a feature,
+++// - `kSetters` a table of setters function pointers from feature enum to set a
+++// feature,
+++// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
+++// flags,
+++// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
+++// their feature enum.
+++
+++#ifndef SRC_DEFINE_TABLES_H_
+++#define SRC_DEFINE_TABLES_H_
+++
+++#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
+++static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
+++#undef FEATURE
+++
+++#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
+++#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
+++  [ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
+++static const HardwareCapabilities kHardwareCapabilities[] = {
+++    DEFINE_TABLE_FEATURES};
+++#undef FEATURE
+++#endif  // DEFINE_TABLE_DONT_GENERATE_HWCAPS
+++
+++#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)                    \
+++  static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) { \
+++    features->NAME = value;                                                 \
+++  }                                                                         \
+++  static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) {        \
+++    return features->NAME;                                                  \
+++  }
+++DEFINE_TABLE_FEATURES
+++#undef FEATURE
+++
+++#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
+++static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
+++                                bool) = {DEFINE_TABLE_FEATURES};
+++#undef FEATURE
+++
+++#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
+++static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
+++    DEFINE_TABLE_FEATURES};
+++#undef FEATURE
+++
+++#endif  // SRC_DEFINE_TABLES_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..46c99066922c8eee41b2ac80e8ae654b270d4636
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,62 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/filesystem.h"
+++
+++#include <errno.h>
+++#include <fcntl.h>
+++#include <stdlib.h>
+++#include <sys/stat.h>
+++#include <sys/types.h>
+++
+++#if defined(CPU_FEATURES_MOCK_FILESYSTEM)
+++// Implementation will be provided by test/filesystem_for_testing.cc.
+++#elif defined(_MSC_VER)
+++#include <io.h>
+++int CpuFeatures_OpenFile(const char* filename) {
+++  int fd = -1;
+++  _sopen_s(&fd, filename, _O_RDONLY, _SH_DENYWR, _S_IREAD);
+++  return fd;
+++}
+++
+++void CpuFeatures_CloseFile(int file_descriptor) { _close(file_descriptor); }
+++
+++int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
+++                         size_t buffer_size) {
+++  return _read(file_descriptor, buffer, (unsigned int)buffer_size);
+++}
+++
+++#else
+++#include <unistd.h>
+++
+++int CpuFeatures_OpenFile(const char* filename) {
+++  int result;
+++  do {
+++    result = open(filename, O_RDONLY);
+++  } while (result == -1L && errno == EINTR);
+++  return result;
+++}
+++
+++void CpuFeatures_CloseFile(int file_descriptor) { close(file_descriptor); }
+++
+++int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
+++                         size_t buffer_size) {
+++  int result;
+++  do {
+++    result = read(file_descriptor, buffer, buffer_size);
+++  } while (result == -1L && errno == EINTR);
+++  return result;
+++}
+++
+++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dd17e3bc6c92b6b3b94f572d16505a8ed4e67eca
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,182 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/hwcaps.h"
+++
+++#include <stdlib.h>
+++#include <string.h>
+++
+++#include "cpu_features_macros.h"
+++#include "internal/filesystem.h"
+++#include "internal/string_view.h"
+++
+++static bool IsSet(const uint32_t mask, const uint32_t value) {
+++  if (mask == 0) return false;
+++  return (value & mask) == mask;
+++}
+++
+++bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+++                             const HardwareCapabilities hwcaps) {
+++  return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
+++         IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
+++}
+++
+++#ifdef CPU_FEATURES_TEST
+++// In test mode, hwcaps_for_testing will define the following functions.
+++HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+++PlatformType CpuFeatures_GetPlatformType(void);
+++#else
+++
+++// Debug facilities
+++#if defined(NDEBUG)
+++#define D(...)
+++#else
+++#include <stdio.h>
+++#define D(...)           \
+++  do {                   \
+++    printf(__VA_ARGS__); \
+++    fflush(stdout);      \
+++  } while (0)
+++#endif
+++
+++////////////////////////////////////////////////////////////////////////////////
+++// Implementation of GetElfHwcapFromGetauxval
+++////////////////////////////////////////////////////////////////////////////////
+++
+++#define AT_HWCAP 16
+++#define AT_HWCAP2 26
+++#define AT_PLATFORM 15
+++#define AT_BASE_PLATFORM 24
+++
+++#if defined(HAVE_STRONG_GETAUXVAL)
+++#include <sys/auxv.h>
+++static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
+++  return getauxval(hwcap_type);
+++}
+++#elif defined(HAVE_DLFCN_H)
+++// On Android we probe the system's C library for a 'getauxval' function and
+++// call it if it exits, or return 0 for failure. This function is available
+++// since API level 20.
+++//
+++// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge
+++// case where some NDK developers use headers for a platform that is newer than
+++// the one really targetted by their application. This is typically done to use
+++// newer native APIs only when running on more recent Android versions, and
+++// requires careful symbol management.
+++//
+++// Note that getauxval() can't really be re-implemented here, because its
+++// implementation does not parse /proc/self/auxv. Instead it depends on values
+++// that are passed by the kernel at process-init time to the C runtime
+++// initialization layer.
+++
+++#include <dlfcn.h>
+++
+++typedef unsigned long getauxval_func_t(unsigned long);
+++
+++static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
+++  uint32_t ret = 0;
+++  void *libc_handle = NULL;
+++  getauxval_func_t *func = NULL;
+++
+++  dlerror();  // Cleaning error state before calling dlopen.
+++  libc_handle = dlopen("libc.so", RTLD_NOW);
+++  if (!libc_handle) {
+++    D("Could not dlopen() C library: %s\n", dlerror());
+++    return 0;
+++  }
+++  func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
+++  if (!func) {
+++    D("Could not find getauxval() in C library\n");
+++  } else {
+++    // Note: getauxval() returns 0 on failure. Doesn't touch errno.
+++    ret = (uint32_t)(*func)(hwcap_type);
+++  }
+++  dlclose(libc_handle);
+++  return ret;
+++}
+++#else
+++#error "This platform does not provide hardware capabilities."
+++#endif
+++
+++// Implementation of GetHardwareCapabilities for OS that provide
+++// GetElfHwcapFromGetauxval().
+++
+++// Fallback when getauxval is not available, retrieves hwcaps from
+++// "/proc/self/auxv".
+++static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
+++  struct {
+++    uint32_t tag;
+++    uint32_t value;
+++  } entry;
+++  uint32_t result = 0;
+++  const char filepath[] = "/proc/self/auxv";
+++  const int fd = CpuFeatures_OpenFile(filepath);
+++  if (fd < 0) {
+++    D("Could not open %s\n", filepath);
+++    return 0;
+++  }
+++  for (;;) {
+++    const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
+++    if (ret < 0) {
+++      D("Error while reading %s\n", filepath);
+++      break;
+++    }
+++    // Detect end of list.
+++    if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
+++      break;
+++    }
+++    if (entry.tag == hwcap_type) {
+++      result = entry.value;
+++      break;
+++    }
+++  }
+++  CpuFeatures_CloseFile(fd);
+++  return result;
+++}
+++
+++// Retrieves hardware capabilities by first trying to call getauxval, if not
+++// available falls back to reading "/proc/self/auxv".
+++static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
+++  unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
+++  if (!hwcaps) {
+++    D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
+++    hwcaps = GetElfHwcapFromProcSelfAuxv(type);
+++  }
+++  return hwcaps;
+++}
+++
+++HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
+++  HardwareCapabilities capabilities;
+++  capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
+++  capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
+++  return capabilities;
+++}
+++
+++PlatformType kEmptyPlatformType;
+++
+++PlatformType CpuFeatures_GetPlatformType(void) {
+++  PlatformType type = kEmptyPlatformType;
+++  char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
+++  char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
+++
+++  if (platform != NULL)
+++    CpuFeatures_StringView_CopyString(str(platform), type.platform,
+++                                      sizeof(type.platform));
+++  if (base_platform != NULL)
+++    CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform,
+++                                      sizeof(type.base_platform));
+++  return type;
+++}
+++
+++#endif  // CPU_FEATURES_TEST
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ffc778d31597913cb254248d6ee34c4f395a037d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,132 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/stack_line_reader.h"
+++
+++#include <assert.h>
+++#include <errno.h>
+++#include <stdio.h>
+++
+++#include "internal/filesystem.h"
+++
+++void StackLineReader_Initialize(StackLineReader* reader, int fd) {
+++  reader->view.ptr = reader->buffer;
+++  reader->view.size = 0;
+++  reader->skip_mode = false;
+++  reader->fd = fd;
+++}
+++
+++// Replaces the content of buffer with bytes from the file.
+++static int LoadFullBuffer(StackLineReader* reader) {
+++  const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer,
+++                                        STACK_LINE_READER_BUFFER_SIZE);
+++  assert(read >= 0);
+++  reader->view.ptr = reader->buffer;
+++  reader->view.size = read;
+++  return read;
+++}
+++
+++// Appends with bytes from the file to buffer, filling the remaining space.
+++static int LoadMore(StackLineReader* reader) {
+++  char* const ptr = reader->buffer + reader->view.size;
+++  const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size;
+++  const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read);
+++  assert(read >= 0);
+++  assert(read <= (int)size_to_read);
+++  reader->view.size += read;
+++  return read;
+++}
+++
+++static int IndexOfEol(StackLineReader* reader) {
+++  return CpuFeatures_StringView_IndexOfChar(reader->view, '\n');
+++}
+++
+++// Relocate buffer's pending bytes at the beginning of the array and fills the
+++// remaining space with bytes from the file.
+++static int BringToFrontAndLoadMore(StackLineReader* reader) {
+++  if (reader->view.size && reader->view.ptr != reader->buffer) {
+++    memmove(reader->buffer, reader->view.ptr, reader->view.size);
+++  }
+++  reader->view.ptr = reader->buffer;
+++  return LoadMore(reader);
+++}
+++
+++// Loads chunks of buffer size from disks until it contains a newline character
+++// or end of file.
+++static void SkipToNextLine(StackLineReader* reader) {
+++  for (;;) {
+++    const int read = LoadFullBuffer(reader);
+++    if (read == 0) {
+++      break;
+++    } else {
+++      const int eol_index = IndexOfEol(reader);
+++      if (eol_index >= 0) {
+++        reader->view =
+++            CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
+++        break;
+++      }
+++    }
+++  }
+++}
+++
+++static LineResult CreateLineResult(bool eof, bool full_line, StringView view) {
+++  LineResult result;
+++  result.eof = eof;
+++  result.full_line = full_line;
+++  result.line = view;
+++  return result;
+++}
+++
+++// Helper methods to provide clearer semantic in StackLineReader_NextLine.
+++static LineResult CreateEOFLineResult(StringView view) {
+++  return CreateLineResult(true, true, view);
+++}
+++
+++static LineResult CreateTruncatedLineResult(StringView view) {
+++  return CreateLineResult(false, false, view);
+++}
+++
+++static LineResult CreateValidLineResult(StringView view) {
+++  return CreateLineResult(false, true, view);
+++}
+++
+++LineResult StackLineReader_NextLine(StackLineReader* reader) {
+++  if (reader->skip_mode) {
+++    SkipToNextLine(reader);
+++    reader->skip_mode = false;
+++  }
+++  {
+++    const bool can_load_more =
+++        reader->view.size < STACK_LINE_READER_BUFFER_SIZE;
+++    int eol_index = IndexOfEol(reader);
+++    if (eol_index < 0 && can_load_more) {
+++      const int read = BringToFrontAndLoadMore(reader);
+++      if (read == 0) {
+++        return CreateEOFLineResult(reader->view);
+++      }
+++      eol_index = IndexOfEol(reader);
+++    }
+++    if (eol_index < 0) {
+++      reader->skip_mode = true;
+++      return CreateTruncatedLineResult(reader->view);
+++    }
+++    {
+++      StringView line =
+++          CpuFeatures_StringView_KeepFront(reader->view, eol_index);
+++      reader->view =
+++          CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
+++      return CreateValidLineResult(line);
+++    }
+++  }
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dc3158fff266f4e162c1f8d32583c06ad183fe9e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,182 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/string_view.h"
+++
+++#include <assert.h>
+++#include <ctype.h>
+++#include <string.h>
+++
+++int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
+++  if (view.ptr && view.size) {
+++    const char* const found = (const char*)memchr(view.ptr, c, view.size);
+++    if (found) {
+++      return (int)(found - view.ptr);
+++    }
+++  }
+++  return -1;
+++}
+++
+++int CpuFeatures_StringView_IndexOf(const StringView view,
+++                                   const StringView sub_view) {
+++  if (sub_view.size) {
+++    StringView remainder = view;
+++    while (remainder.size >= sub_view.size) {
+++      const int found_index =
+++          CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
+++      if (found_index < 0) break;
+++      remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
+++      if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
+++        return (int)(remainder.ptr - view.ptr);
+++      }
+++      remainder = CpuFeatures_StringView_PopFront(remainder, 1);
+++    }
+++  }
+++  return -1;
+++}
+++
+++bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
+++  if (a.size == b.size) {
+++    return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0;
+++  }
+++  return false;
+++}
+++
+++bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
+++  return a.ptr && b.ptr && b.size && a.size >= b.size
+++             ? memcmp(a.ptr, b.ptr, b.size) == 0
+++             : false;
+++}
+++
+++StringView CpuFeatures_StringView_PopFront(const StringView str_view,
+++                                           size_t count) {
+++  if (count > str_view.size) {
+++    return kEmptyStringView;
+++  }
+++  return view(str_view.ptr + count, str_view.size - count);
+++}
+++
+++StringView CpuFeatures_StringView_PopBack(const StringView str_view,
+++                                          size_t count) {
+++  if (count > str_view.size) {
+++    return kEmptyStringView;
+++  }
+++  return view(str_view.ptr, str_view.size - count);
+++}
+++
+++StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
+++                                            size_t count) {
+++  return count <= str_view.size ? view(str_view.ptr, count) : str_view;
+++}
+++
+++char CpuFeatures_StringView_Front(const StringView view) {
+++  assert(view.size);
+++  assert(view.ptr);
+++  return view.ptr[0];
+++}
+++
+++char CpuFeatures_StringView_Back(const StringView view) {
+++  assert(view.size);
+++  return view.ptr[view.size - 1];
+++}
+++
+++StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
+++  while (view.size && isspace(CpuFeatures_StringView_Front(view)))
+++    view = CpuFeatures_StringView_PopFront(view, 1);
+++  while (view.size && isspace(CpuFeatures_StringView_Back(view)))
+++    view = CpuFeatures_StringView_PopBack(view, 1);
+++  return view;
+++}
+++
+++static int HexValue(const char c) {
+++  if (c >= '0' && c <= '9') return c - '0';
+++  if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+++  if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+++  return -1;
+++}
+++
+++// Returns -1 if view contains non digits.
+++static int ParsePositiveNumberWithBase(const StringView view, int base) {
+++  int result = 0;
+++  StringView remainder = view;
+++  for (; remainder.size;
+++       remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
+++    const int value = HexValue(CpuFeatures_StringView_Front(remainder));
+++    if (value < 0 || value >= base) return -1;
+++    result = (result * base) + value;
+++  }
+++  return result;
+++}
+++
+++int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
+++  if (view.size) {
+++    const StringView hex_prefix = str("0x");
+++    if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
+++      const StringView span_no_prefix =
+++          CpuFeatures_StringView_PopFront(view, hex_prefix.size);
+++      return ParsePositiveNumberWithBase(span_no_prefix, 16);
+++    }
+++    return ParsePositiveNumberWithBase(view, 10);
+++  }
+++  return -1;
+++}
+++
+++void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
+++                                       size_t dst_size) {
+++  if (dst_size > 0) {
+++    const size_t max_copy_size = dst_size - 1;
+++    const size_t copy_size =
+++        src.size > max_copy_size ? max_copy_size : src.size;
+++    memcpy(dst, src.ptr, copy_size);
+++    dst[copy_size] = '\0';
+++  }
+++}
+++
+++bool CpuFeatures_StringView_HasWord(const StringView line,
+++                                    const char* const word_str) {
+++  const StringView word = str(word_str);
+++  StringView remainder = line;
+++  for (;;) {
+++    const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
+++    if (index_of_word < 0) {
+++      return false;
+++    } else {
+++      const StringView before =
+++          CpuFeatures_StringView_KeepFront(line, index_of_word);
+++      const StringView after =
+++          CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
+++      const bool valid_before =
+++          before.size == 0 || CpuFeatures_StringView_Back(before) == ' ';
+++      const bool valid_after =
+++          after.size == 0 || CpuFeatures_StringView_Front(after) == ' ';
+++      if (valid_before && valid_after) return true;
+++      remainder =
+++          CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
+++    }
+++  }
+++  return false;
+++}
+++
+++bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
+++                                                 StringView* key,
+++                                                 StringView* value) {
+++  const StringView sep = str(": ");
+++  const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
+++  if (index_of_separator < 0) return false;
+++  *value = CpuFeatures_StringView_TrimWhitespace(
+++      CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size));
+++  *key = CpuFeatures_StringView_TrimWhitespace(
+++      CpuFeatures_StringView_KeepFront(line, index_of_separator));
+++  return true;
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c80ffc5c87c8e1dbacde5c620712e53c9d858cf8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,438 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// This program dumps current host data to the standard output.
+++// Output can be text or json if the `--json` flag is passed.
+++
+++#include <assert.h>
+++#include <stdarg.h>
+++#include <stdbool.h>
+++#include <stdint.h>
+++#include <stdio.h>
+++#include <stdlib.h>
+++#include <string.h>
+++
+++#include "cpu_features_macros.h"
+++
+++#if defined(CPU_FEATURES_ARCH_X86)
+++#include "cpuinfo_x86.h"
+++#elif defined(CPU_FEATURES_ARCH_ARM)
+++#include "cpuinfo_arm.h"
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++#include "cpuinfo_aarch64.h"
+++#elif defined(CPU_FEATURES_ARCH_MIPS)
+++#include "cpuinfo_mips.h"
+++#elif defined(CPU_FEATURES_ARCH_PPC)
+++#include "cpuinfo_ppc.h"
+++#endif
+++
+++// Design principles
+++// -----------------
+++// We build a tree structure containing all the data to be displayed.
+++// Then depending on the output type (text or json) we walk the tree and display
+++// the data accordingly.
+++
+++// We use a bump allocator to allocate strings and nodes of the tree,
+++// Memory is not intended to be reclaimed.
+++typedef struct {
+++  char* ptr;
+++  size_t size;
+++} BumpAllocator;
+++
+++char gGlobalBuffer[64 * 1024];
+++BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
+++                                .size = sizeof(gGlobalBuffer)};
+++
+++static void internal_error() {
+++  fputs("internal error\n", stderr);
+++  exit(EXIT_FAILURE);
+++}
+++
+++#define ALIGN 8
+++
+++static void assertAligned() {
+++  if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
+++}
+++
+++static void BA_Align() {
+++  while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
+++    --gBumpAllocator.size;
+++    ++gBumpAllocator.ptr;
+++  }
+++  assertAligned();
+++}
+++
+++// Update the available memory left in the BumpAllocator.
+++static void* BA_Bump(size_t size) {
+++  assertAligned();
+++  // Align size to next 8B boundary.
+++  size = (size + ALIGN - 1) / ALIGN * ALIGN;
+++  if (gBumpAllocator.size < size) internal_error();
+++  void* ptr = gBumpAllocator.ptr;
+++  gBumpAllocator.size -= size;
+++  gBumpAllocator.ptr += size;
+++  return ptr;
+++}
+++
+++// The type of the nodes in the tree.
+++typedef enum {
+++  NT_INVALID,
+++  NT_INT,
+++  NT_MAP,
+++  NT_MAP_ENTRY,
+++  NT_ARRAY,
+++  NT_ARRAY_ELEMENT,
+++  NT_STRING,
+++} NodeType;
+++
+++// The node in the tree.
+++typedef struct Node {
+++  NodeType type;
+++  unsigned integer;
+++  const char* string;
+++  struct Node* value;
+++  struct Node* next;
+++} Node;
+++
+++// Creates an initialized Node.
+++static Node* BA_CreateNode(NodeType type) {
+++  Node* tv = (Node*)BA_Bump(sizeof(Node));
+++  assert(tv);
+++  *tv = (Node){.type = type};
+++  return tv;
+++}
+++
+++// Adds an integer node.
+++static Node* CreateInt(int value) {
+++  Node* tv = BA_CreateNode(NT_INT);
+++  tv->integer = value;
+++  return tv;
+++}
+++
+++// Adds a string node.
+++// `value` must outlive the tree.
+++static Node* CreateConstantString(const char* value) {
+++  Node* tv = BA_CreateNode(NT_STRING);
+++  tv->string = value;
+++  return tv;
+++}
+++
+++// Adds a map node.
+++static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
+++
+++// Adds an array node.
+++static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
+++
+++// Adds a formatted string node.
+++static Node* CreatePrintfString(const char* format, ...) {
+++  va_list arglist;
+++  va_start(arglist, format);
+++  char* const ptr = gBumpAllocator.ptr;
+++  const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist);
+++  va_end(arglist);
+++  if (written < 0 || written >= (int)gBumpAllocator.size) internal_error();
+++  return CreateConstantString((char*)BA_Bump(written));
+++}
+++
+++// Adds a string node.
+++static Node* CreateString(const char* value) {
+++  return CreatePrintfString("%s", value);
+++}
+++
+++// Adds a map entry node.
+++static void AddMapEntry(Node* map, const char* key, Node* value) {
+++  assert(map && map->type == NT_MAP);
+++  Node* current = map;
+++  while (current->next) current = current->next;
+++  current->next = (Node*)BA_Bump(sizeof(Node));
+++  *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value};
+++}
+++
+++// Adds an array element node.
+++static void AddArrayElement(Node* array, Node* value) {
+++  assert(array && array->type == NT_ARRAY);
+++  Node* current = array;
+++  while (current->next) current = current->next;
+++  current->next = (Node*)BA_Bump(sizeof(Node));
+++  *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value};
+++}
+++
+++static int cmp(const void* p1, const void* p2) {
+++  return strcmp(*(const char* const*)p1, *(const char* const*)p2);
+++}
+++
+++#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
+++  static void AddFlags(Node* map, const FeatureType* features) {         \
+++    size_t i;                                                            \
+++    const char* ptrs[LastEnum] = {0};                                    \
+++    size_t count = 0;                                                    \
+++    for (i = 0; i < LastEnum; ++i) {                                     \
+++      if (HasFeature(features, i)) {                                     \
+++        ptrs[count] = FeatureName(i);                                    \
+++        ++count;                                                         \
+++      }                                                                  \
+++    }                                                                    \
+++    qsort((void*)ptrs, count, sizeof(char*), cmp);                       \
+++    Node* const array = CreateArray();                                   \
+++    for (i = 0; i < count; ++i)                                          \
+++      AddArrayElement(array, CreateConstantString(ptrs[i]));             \
+++    AddMapEntry(map, "flags", array);                                    \
+++  }
+++
+++#if defined(CPU_FEATURES_ARCH_X86)
+++DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
+++                 X86_LAST_)
+++#elif defined(CPU_FEATURES_ARCH_ARM)
+++DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
+++                 ARM_LAST_)
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
+++                 Aarch64Features, AARCH64_LAST_)
+++#elif defined(CPU_FEATURES_ARCH_MIPS)
+++DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
+++                 MipsFeatures, MIPS_LAST_)
+++#elif defined(CPU_FEATURES_ARCH_PPC)
+++DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
+++                 PPC_LAST_)
+++#endif
+++
+++// Prints a json string with characters escaping.
+++static void printJsonString(const char* str) {
+++  putchar('"');
+++  for (; str && *str; ++str) {
+++    switch (*str) {
+++      case '\"':
+++      case '\\':
+++      case '/':
+++      case '\b':
+++      case '\f':
+++      case '\n':
+++      case '\r':
+++      case '\t':
+++        putchar('\\');
+++    }
+++    putchar(*str);
+++  }
+++  putchar('"');
+++}
+++
+++// Walks a Node and print it as json.
+++static void printJson(const Node* current) {
+++  assert(current);
+++  switch (current->type) {
+++    case NT_INVALID:
+++      break;
+++    case NT_INT:
+++      printf("%d", current->integer);
+++      break;
+++    case NT_STRING:
+++      printJsonString(current->string);
+++      break;
+++    case NT_ARRAY:
+++      putchar('[');
+++      if (current->next) printJson(current->next);
+++      putchar(']');
+++      break;
+++    case NT_MAP:
+++      putchar('{');
+++      if (current->next) printJson(current->next);
+++      putchar('}');
+++      break;
+++    case NT_MAP_ENTRY:
+++      printf("\"%s\":", current->string);
+++      printJson(current->value);
+++      if (current->next) {
+++        putchar(',');
+++        printJson(current->next);
+++      }
+++      break;
+++    case NT_ARRAY_ELEMENT:
+++      printJson(current->value);
+++      if (current->next) {
+++        putchar(',');
+++        printJson(current->next);
+++      }
+++      break;
+++  }
+++}
+++
+++// Walks a Node and print it as text.
+++static void printTextField(const Node* current) {
+++  switch (current->type) {
+++    case NT_INVALID:
+++      break;
+++    case NT_INT:
+++      printf("%3d (0x%02X)", current->integer, current->integer);
+++      break;
+++    case NT_STRING:
+++      fputs(current->string, stdout);
+++      break;
+++    case NT_ARRAY:
+++      if (current->next) printTextField(current->next);
+++      break;
+++    case NT_MAP:
+++      if (current->next) {
+++        printf("{");
+++        printJson(current->next);
+++        printf("}");
+++      }
+++      break;
+++    case NT_MAP_ENTRY:
+++      printf("%-15s : ", current->string);
+++      printTextField(current->value);
+++      if (current->next) {
+++        putchar('\n');
+++        printTextField(current->next);
+++      }
+++      break;
+++    case NT_ARRAY_ELEMENT:
+++      printTextField(current->value);
+++      if (current->next) {
+++        putchar(',');
+++        printTextField(current->next);
+++      }
+++      break;
+++  }
+++}
+++
+++static void printTextRoot(const Node* current) {
+++  if (current->type == NT_MAP && current->next) printTextField(current->next);
+++}
+++
+++static void showUsage(const char* name) {
+++  printf(
+++      "\n"
+++      "Usage: %s [options]\n"
+++      "      Options:\n"
+++      "      -h | --help     Show help message.\n"
+++      "      -j | --json     Format output as json instead of plain text.\n"
+++      "\n",
+++      name);
+++}
+++
+++static Node* GetCacheTypeString(CacheType cache_type) {
+++  switch (cache_type) {
+++    case CPU_FEATURE_CACHE_NULL:
+++      return CreateConstantString("null");
+++    case CPU_FEATURE_CACHE_DATA:
+++      return CreateConstantString("data");
+++    case CPU_FEATURE_CACHE_INSTRUCTION:
+++      return CreateConstantString("instruction");
+++    case CPU_FEATURE_CACHE_UNIFIED:
+++      return CreateConstantString("unified");
+++    case CPU_FEATURE_CACHE_TLB:
+++      return CreateConstantString("tlb");
+++    case CPU_FEATURE_CACHE_DTLB:
+++      return CreateConstantString("dtlb");
+++    case CPU_FEATURE_CACHE_STLB:
+++      return CreateConstantString("stlb");
+++    case CPU_FEATURE_CACHE_PREFETCH:
+++      return CreateConstantString("prefetch");
+++  }
+++}
+++
+++static void AddCacheInfo(Node* root, const CacheInfo* cache_info) {
+++  Node* array = CreateArray();
+++  for (int i = 0; i < cache_info->size; ++i) {
+++    CacheLevelInfo info = cache_info->levels[i];
+++    Node* map = CreateMap();
+++    AddMapEntry(map, "level", CreateInt(info.level));
+++    AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type));
+++    AddMapEntry(map, "cache_size", CreateInt(info.cache_size));
+++    AddMapEntry(map, "ways", CreateInt(info.ways));
+++    AddMapEntry(map, "line_size", CreateInt(info.line_size));
+++    AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries));
+++    AddMapEntry(map, "partitioning", CreateInt(info.partitioning));
+++    AddArrayElement(array, map);
+++  }
+++  AddMapEntry(root, "cache_info", array);
+++}
+++
+++static Node* CreateTree() {
+++  Node* root = CreateMap();
+++#if defined(CPU_FEATURES_ARCH_X86)
+++  char brand_string[49];
+++  const X86Info info = GetX86Info();
+++  const CacheInfo cache_info = GetX86CacheInfo();
+++  FillX86BrandString(brand_string);
+++  AddMapEntry(root, "arch", CreateString("x86"));
+++  AddMapEntry(root, "brand", CreateString(brand_string));
+++  AddMapEntry(root, "family", CreateInt(info.family));
+++  AddMapEntry(root, "model", CreateInt(info.model));
+++  AddMapEntry(root, "stepping", CreateInt(info.stepping));
+++  AddMapEntry(root, "uarch",
+++              CreateString(
+++                  GetX86MicroarchitectureName(GetX86Microarchitecture(&info))));
+++  AddFlags(root, &info.features);
+++  AddCacheInfo(root, &cache_info);
+++#elif defined(CPU_FEATURES_ARCH_ARM)
+++  const ArmInfo info = GetArmInfo();
+++  AddMapEntry(root, "arch", CreateString("ARM"));
+++  AddMapEntry(root, "implementer", CreateInt(info.implementer));
+++  AddMapEntry(root, "architecture", CreateInt(info.architecture));
+++  AddMapEntry(root, "variant", CreateInt(info.variant));
+++  AddMapEntry(root, "part", CreateInt(info.part));
+++  AddMapEntry(root, "revision", CreateInt(info.revision));
+++  AddFlags(root, &info.features);
+++#elif defined(CPU_FEATURES_ARCH_AARCH64)
+++  const Aarch64Info info = GetAarch64Info();
+++  AddMapEntry(root, "arch", CreateString("aarch64"));
+++  AddMapEntry(root, "implementer", CreateInt(info.implementer));
+++  AddMapEntry(root, "variant", CreateInt(info.variant));
+++  AddMapEntry(root, "part", CreateInt(info.part));
+++  AddMapEntry(root, "revision", CreateInt(info.revision));
+++  AddFlags(root, &info.features);
+++#elif defined(CPU_FEATURES_ARCH_MIPS)
+++  const MipsInfo info = GetMipsInfo();
+++  AddMapEntry(root, "arch", CreateString("mips"));
+++  AddFlags(root, &info.features);
+++#elif defined(CPU_FEATURES_ARCH_PPC)
+++  const PPCInfo info = GetPPCInfo();
+++  const PPCPlatformStrings strings = GetPPCPlatformStrings();
+++  AddMapEntry(root, "arch", CreateString("ppc"));
+++  AddMapEntry(root, "platform", CreateString(strings.platform));
+++  AddMapEntry(root, "model", CreateString(strings.model));
+++  AddMapEntry(root, "machine", CreateString(strings.machine));
+++  AddMapEntry(root, "cpu", CreateString(strings.cpu));
+++  AddMapEntry(root, "instruction", CreateString(strings.type.platform));
+++  AddMapEntry(root, "microarchitecture",
+++              CreateString(strings.type.base_platform));
+++  AddFlags(root, &info.features);
+++#endif
+++  return root;
+++}
+++
+++int main(int argc, char** argv) {
+++  BA_Align();
+++  const Node* const root = CreateTree();
+++  bool outputJson = false;
+++  int i = 1;
+++  for (; i < argc; ++i) {
+++    const char* arg = argv[i];
+++    if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
+++      outputJson = true;
+++    } else {
+++      showUsage(argv[0]);
+++      if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
+++        return EXIT_SUCCESS;
+++      return EXIT_FAILURE;
+++    }
+++  }
+++  if (outputJson)
+++    printJson(root);
+++  else
+++    printTextRoot(root);
+++  putchar('\n');
+++  return EXIT_SUCCESS;
+++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c10e617a9fd4c175b23b87c811f1c3477aa82168
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,85 @@@@
+++#
+++# libraries for tests
+++#
+++
+++include_directories(../include)
+++add_definitions(-DCPU_FEATURES_TEST)
+++
+++##------------------------------------------------------------------------------
+++add_library(string_view ../src/string_view.c)
+++##------------------------------------------------------------------------------
+++add_library(filesystem_for_testing filesystem_for_testing.cc)
+++target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
+++##------------------------------------------------------------------------------
+++add_library(hwcaps_for_testing hwcaps_for_testing.cc)
+++target_link_libraries(hwcaps_for_testing filesystem_for_testing)
+++##------------------------------------------------------------------------------
+++add_library(stack_line_reader ../src/stack_line_reader.c)
+++target_compile_definitions(stack_line_reader PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024)
+++target_link_libraries(stack_line_reader string_view)
+++##------------------------------------------------------------------------------
+++add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
+++target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
+++target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
+++##------------------------------------------------------------------------------
+++add_library(all_libraries ../src/hwcaps.c  ../src/stack_line_reader.c)
+++target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
+++
+++#
+++# tests
+++#
+++link_libraries(gtest gmock_main)
+++
+++## bit_utils_test
+++add_executable(bit_utils_test bit_utils_test.cc)
+++target_link_libraries(bit_utils_test)
+++add_test(NAME bit_utils_test COMMAND bit_utils_test)
+++##------------------------------------------------------------------------------
+++## string_view_test
+++add_executable(string_view_test string_view_test.cc ../src/string_view.c)
+++target_link_libraries(string_view_test string_view)
+++add_test(NAME string_view_test COMMAND string_view_test)
+++##------------------------------------------------------------------------------
+++## stack_line_reader_test
+++add_executable(stack_line_reader_test stack_line_reader_test.cc)
+++target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
+++add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
+++##------------------------------------------------------------------------------
+++## cpuinfo_x86_test
+++if(PROCESSOR_IS_X86)
+++  add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
+++  target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
+++  if(APPLE)
+++    target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
+++  endif()
+++  target_link_libraries(cpuinfo_x86_test all_libraries)
+++  add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
+++endif()
+++##------------------------------------------------------------------------------
+++## cpuinfo_arm_test
+++if(PROCESSOR_IS_ARM)
+++  add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c)
+++  target_link_libraries(cpuinfo_arm_test all_libraries)
+++  add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
+++endif()
+++##------------------------------------------------------------------------------
+++## cpuinfo_aarch64_test
+++if(PROCESSOR_IS_AARCH64)
+++  add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c)
+++  target_link_libraries(cpuinfo_aarch64_test all_libraries)
+++  add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
+++endif()
+++##------------------------------------------------------------------------------
+++## cpuinfo_mips_test
+++if(PROCESSOR_IS_MIPS)
+++  add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc  ../src/cpuinfo_mips.c)
+++  target_link_libraries(cpuinfo_mips_test all_libraries)
+++  add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
+++endif()
+++##------------------------------------------------------------------------------
+++## cpuinfo_ppc_test
+++if(PROCESSOR_IS_POWER)
+++  add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc  ../src/cpuinfo_ppc.c)
+++  target_link_libraries(cpuinfo_ppc_test all_libraries)
+++  add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
+++endif()
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3874e1309379e3db68d5ffe97c46a1cb70c5d99b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,53 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/bit_utils.h"
+++
+++#include "gtest/gtest.h"
+++
+++namespace cpu_features {
+++namespace {
+++
+++TEST(UtilsTest, IsBitSet) {
+++  for (size_t bit_set = 0; bit_set < 32; ++bit_set) {
+++    const uint32_t value = 1UL << bit_set;
+++    for (uint32_t i = 0; i < 32; ++i) {
+++      EXPECT_EQ(IsBitSet(value, i), i == bit_set);
+++    }
+++  }
+++
+++  // testing 0, all bits should be 0.
+++  for (uint32_t i = 0; i < 32; ++i) {
+++    EXPECT_FALSE(IsBitSet(0, i));
+++  }
+++
+++  // testing ~0, all bits should be 1.
+++  for (uint32_t i = 0; i < 32; ++i) {
+++    EXPECT_TRUE(IsBitSet(-1, i));
+++  }
+++}
+++
+++TEST(UtilsTest, ExtractBitRange) {
+++  // Extracting all bits gives the same number.
+++  EXPECT_EQ(ExtractBitRange(123, 31, 0), 123);
+++  // Extracting 1 bit gives parity.
+++  EXPECT_EQ(ExtractBitRange(123, 0, 0), 1);
+++  EXPECT_EQ(ExtractBitRange(122, 0, 0), 0);
+++
+++  EXPECT_EQ(ExtractBitRange(0xF0, 7, 4), 0xF);
+++  EXPECT_EQ(ExtractBitRange(0x42 << 2, 10, 2), 0x42);
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5afaaa8fc28ce71e0dc7576fddc55f0a80ef58d3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,171 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_aarch64.h"
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++#include "hwcaps_for_testing.h"
+++
+++namespace cpu_features {
+++namespace {
+++
+++void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
+++
+++TEST(CpuinfoAarch64Test, FromHardwareCap) {
+++  SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetAarch64Info();
+++  EXPECT_TRUE(info.features.fp);
+++  EXPECT_FALSE(info.features.asimd);
+++  EXPECT_FALSE(info.features.evtstrm);
+++  EXPECT_TRUE(info.features.aes);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++  EXPECT_FALSE(info.features.crc32);
+++  EXPECT_FALSE(info.features.atomics);
+++  EXPECT_FALSE(info.features.fphp);
+++  EXPECT_FALSE(info.features.asimdhp);
+++  EXPECT_FALSE(info.features.cpuid);
+++  EXPECT_FALSE(info.features.asimdrdm);
+++  EXPECT_FALSE(info.features.jscvt);
+++  EXPECT_FALSE(info.features.fcma);
+++  EXPECT_FALSE(info.features.lrcpc);
+++  EXPECT_FALSE(info.features.dcpop);
+++  EXPECT_FALSE(info.features.sha3);
+++  EXPECT_FALSE(info.features.sm3);
+++  EXPECT_FALSE(info.features.sm4);
+++  EXPECT_FALSE(info.features.asimddp);
+++  EXPECT_FALSE(info.features.sha512);
+++  EXPECT_FALSE(info.features.sve);
+++  EXPECT_FALSE(info.features.asimdfhm);
+++  EXPECT_FALSE(info.features.dit);
+++  EXPECT_FALSE(info.features.uscat);
+++  EXPECT_FALSE(info.features.ilrcpc);
+++  EXPECT_FALSE(info.features.flagm);
+++  EXPECT_FALSE(info.features.ssbs);
+++  EXPECT_FALSE(info.features.sb);
+++  EXPECT_FALSE(info.features.paca);
+++  EXPECT_FALSE(info.features.pacg);
+++}
+++
+++TEST(CpuinfoAarch64Test, FromHardwareCap2) {
+++  SetHardwareCapabilities(AARCH64_HWCAP_FP,
+++                          AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetAarch64Info();
+++  EXPECT_TRUE(info.features.fp);
+++
+++  EXPECT_TRUE(info.features.sve2);
+++  EXPECT_TRUE(info.features.bti);
+++
+++  EXPECT_FALSE(info.features.dcpodp);
+++  EXPECT_FALSE(info.features.sveaes);
+++  EXPECT_FALSE(info.features.svepmull);
+++  EXPECT_FALSE(info.features.svebitperm);
+++  EXPECT_FALSE(info.features.svesha3);
+++  EXPECT_FALSE(info.features.svesm4);
+++  EXPECT_FALSE(info.features.flagm2);
+++  EXPECT_FALSE(info.features.frint);
+++  EXPECT_FALSE(info.features.svei8mm);
+++  EXPECT_FALSE(info.features.svef32mm);
+++  EXPECT_FALSE(info.features.svef64mm);
+++  EXPECT_FALSE(info.features.svebf16);
+++  EXPECT_FALSE(info.features.i8mm);
+++  EXPECT_FALSE(info.features.bf16);
+++  EXPECT_FALSE(info.features.dgh);
+++  EXPECT_FALSE(info.features.rng);
+++}
+++
+++TEST(CpuinfoAarch64Test, ARMCortexA53) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(Processor   : AArch64 Processor rev 3 (aarch64)
+++processor   : 0
+++processor   : 1
+++processor   : 2
+++processor   : 3
+++processor   : 4
+++processor   : 5
+++processor   : 6
+++processor   : 7
+++Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32
+++CPU implementer : 0x41
+++CPU architecture: AArch64
+++CPU variant : 0x0
+++CPU part    : 0xd03
+++CPU revision    : 3)");
+++  const auto info = GetAarch64Info();
+++  EXPECT_EQ(info.implementer, 0x41);
+++  EXPECT_EQ(info.variant, 0x0);
+++  EXPECT_EQ(info.part, 0xd03);
+++  EXPECT_EQ(info.revision, 3);
+++
+++  EXPECT_TRUE(info.features.fp);
+++  EXPECT_TRUE(info.features.asimd);
+++  EXPECT_TRUE(info.features.evtstrm);
+++  EXPECT_TRUE(info.features.aes);
+++  EXPECT_TRUE(info.features.pmull);
+++  EXPECT_TRUE(info.features.sha1);
+++  EXPECT_TRUE(info.features.sha2);
+++  EXPECT_TRUE(info.features.crc32);
+++
+++  EXPECT_FALSE(info.features.atomics);
+++  EXPECT_FALSE(info.features.fphp);
+++  EXPECT_FALSE(info.features.asimdhp);
+++  EXPECT_FALSE(info.features.cpuid);
+++  EXPECT_FALSE(info.features.asimdrdm);
+++  EXPECT_FALSE(info.features.jscvt);
+++  EXPECT_FALSE(info.features.fcma);
+++  EXPECT_FALSE(info.features.lrcpc);
+++  EXPECT_FALSE(info.features.dcpop);
+++  EXPECT_FALSE(info.features.sha3);
+++  EXPECT_FALSE(info.features.sm3);
+++  EXPECT_FALSE(info.features.sm4);
+++  EXPECT_FALSE(info.features.asimddp);
+++  EXPECT_FALSE(info.features.sha512);
+++  EXPECT_FALSE(info.features.sve);
+++  EXPECT_FALSE(info.features.asimdfhm);
+++  EXPECT_FALSE(info.features.dit);
+++  EXPECT_FALSE(info.features.uscat);
+++  EXPECT_FALSE(info.features.ilrcpc);
+++  EXPECT_FALSE(info.features.flagm);
+++  EXPECT_FALSE(info.features.ssbs);
+++  EXPECT_FALSE(info.features.sb);
+++  EXPECT_FALSE(info.features.paca);
+++  EXPECT_FALSE(info.features.pacg);
+++  EXPECT_FALSE(info.features.dcpodp);
+++  EXPECT_FALSE(info.features.sve2);
+++  EXPECT_FALSE(info.features.sveaes);
+++  EXPECT_FALSE(info.features.svepmull);
+++  EXPECT_FALSE(info.features.svebitperm);
+++  EXPECT_FALSE(info.features.svesha3);
+++  EXPECT_FALSE(info.features.svesm4);
+++  EXPECT_FALSE(info.features.flagm2);
+++  EXPECT_FALSE(info.features.frint);
+++  EXPECT_FALSE(info.features.svei8mm);
+++  EXPECT_FALSE(info.features.svef32mm);
+++  EXPECT_FALSE(info.features.svef64mm);
+++  EXPECT_FALSE(info.features.svebf16);
+++  EXPECT_FALSE(info.features.i8mm);
+++  EXPECT_FALSE(info.features.bf16);
+++  EXPECT_FALSE(info.features.dgh);
+++  EXPECT_FALSE(info.features.rng);
+++  EXPECT_FALSE(info.features.bti);
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e0b08a4a69767be658c350938655c53d8d2a60bc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,354 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_arm.h"
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++#include "hwcaps_for_testing.h"
+++
+++namespace cpu_features {
+++namespace {
+++
+++void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
+++
+++TEST(CpuinfoArmTest, FromHardwareCap) {
+++  SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetArmInfo();
+++  EXPECT_TRUE(info.features.vfp);    // triggered by vfpv3
+++  EXPECT_TRUE(info.features.vfpv3);  // triggered by neon
+++  EXPECT_TRUE(info.features.neon);
+++  EXPECT_TRUE(info.features.aes);
+++  EXPECT_TRUE(info.features.crc32);
+++
+++  EXPECT_FALSE(info.features.vfpv4);
+++  EXPECT_FALSE(info.features.iwmmxt);
+++  EXPECT_FALSE(info.features.crunch);
+++  EXPECT_FALSE(info.features.thumbee);
+++  EXPECT_FALSE(info.features.vfpv3d16);
+++  EXPECT_FALSE(info.features.idiva);
+++  EXPECT_FALSE(info.features.idivt);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++
+++  // check some random features with EnumValue():
+++  EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
+++  EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
+++  // out of bound EnumValue() check
+++  EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
+++}
+++
+++TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(processor       : 0
+++model name      : ARMv7 Processor rev 3 (v71)
+++BogoMIPS        : 120.00
+++Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
+++CPU implementer : 0x41
+++CPU architecture: 7
+++CPU variant     : 0x2
+++CPU part        : 0xc0f
+++CPU revision    : 3)");
+++  const auto info = GetArmInfo();
+++  EXPECT_EQ(info.implementer, 0x41);
+++  EXPECT_EQ(info.variant, 0x2);
+++  EXPECT_EQ(info.part, 0xc0f);
+++  EXPECT_EQ(info.revision, 3);
+++  EXPECT_EQ(info.architecture, 7);
+++
+++  EXPECT_FALSE(info.features.swp);
+++  EXPECT_TRUE(info.features.half);
+++  EXPECT_TRUE(info.features.thumb);
+++  EXPECT_FALSE(info.features._26bit);
+++  EXPECT_TRUE(info.features.fastmult);
+++  EXPECT_FALSE(info.features.fpa);
+++  EXPECT_TRUE(info.features.vfp);
+++  EXPECT_TRUE(info.features.edsp);
+++  EXPECT_FALSE(info.features.java);
+++  EXPECT_FALSE(info.features.iwmmxt);
+++  EXPECT_FALSE(info.features.crunch);
+++  EXPECT_FALSE(info.features.thumbee);
+++  EXPECT_TRUE(info.features.neon);
+++  EXPECT_TRUE(info.features.vfpv3);
+++  EXPECT_FALSE(info.features.vfpv3d16);
+++  EXPECT_TRUE(info.features.tls);
+++  EXPECT_TRUE(info.features.vfpv4);
+++  EXPECT_TRUE(info.features.idiva);
+++  EXPECT_TRUE(info.features.idivt);
+++  EXPECT_TRUE(info.features.vfpd32);
+++  EXPECT_TRUE(info.features.lpae);
+++  EXPECT_FALSE(info.features.evtstrm);
+++  EXPECT_FALSE(info.features.aes);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++  EXPECT_FALSE(info.features.crc32);
+++}
+++
+++// Linux test-case
+++TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(processor       : 0
+++model name      : ARMv6-compatible processor rev 7 (v6l)
+++BogoMIPS        : 697.95
+++Features        : half thumb fastmult vfp edsp java tls
+++CPU implementer : 0x41
+++CPU architecture: 7
+++CPU variant     : 0x0
+++CPU part        : 0xb76
+++CPU revision    : 7
+++
+++Hardware        : BCM2835
+++Revision        : 9000c1
+++Serial          : 000000006cd946f3)");
+++  const auto info = GetArmInfo();
+++  EXPECT_EQ(info.implementer, 0x41);
+++  EXPECT_EQ(info.variant, 0x0);
+++  EXPECT_EQ(info.part, 0xb76);
+++  EXPECT_EQ(info.revision, 7);
+++  EXPECT_EQ(info.architecture, 6);
+++
+++  EXPECT_FALSE(info.features.swp);
+++  EXPECT_TRUE(info.features.half);
+++  EXPECT_TRUE(info.features.thumb);
+++  EXPECT_FALSE(info.features._26bit);
+++  EXPECT_TRUE(info.features.fastmult);
+++  EXPECT_FALSE(info.features.fpa);
+++  EXPECT_TRUE(info.features.vfp);
+++  EXPECT_TRUE(info.features.edsp);
+++  EXPECT_TRUE(info.features.java);
+++  EXPECT_FALSE(info.features.iwmmxt);
+++  EXPECT_FALSE(info.features.crunch);
+++  EXPECT_FALSE(info.features.thumbee);
+++  EXPECT_FALSE(info.features.neon);
+++  EXPECT_FALSE(info.features.vfpv3);
+++  EXPECT_FALSE(info.features.vfpv3d16);
+++  EXPECT_TRUE(info.features.tls);
+++  EXPECT_FALSE(info.features.vfpv4);
+++  EXPECT_FALSE(info.features.idiva);
+++  EXPECT_FALSE(info.features.idivt);
+++  EXPECT_FALSE(info.features.vfpd32);
+++  EXPECT_FALSE(info.features.lpae);
+++  EXPECT_FALSE(info.features.evtstrm);
+++  EXPECT_FALSE(info.features.aes);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++  EXPECT_FALSE(info.features.crc32);
+++}
+++
+++TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(processor       : 0
+++model name      : ARMv7 Processor rev 1 (v7l)
+++BogoMIPS        : 50.00
+++Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
+++CPU implementer : 0x41
+++CPU architecture: 7
+++CPU variant     : 0x4
+++CPU part        : 0xc09
+++CPU revision    : 1
+++
+++processor       : 1
+++model name      : ARMv7 Processor rev 1 (v7l)
+++BogoMIPS        : 50.00
+++Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
+++CPU implementer : 0x41
+++CPU architecture: 7
+++CPU variant     : 0x4
+++CPU part        : 0xc09
+++CPU revision    : 1
+++
+++Hardware        : Marvell Armada 380/385 (Device Tree)
+++Revision        : 0000
+++Serial          : 0000000000000000)");
+++  const auto info = GetArmInfo();
+++  EXPECT_EQ(info.implementer, 0x41);
+++  EXPECT_EQ(info.variant, 0x4);
+++  EXPECT_EQ(info.part, 0xc09);
+++  EXPECT_EQ(info.revision, 1);
+++  EXPECT_EQ(info.architecture, 7);
+++
+++  EXPECT_FALSE(info.features.swp);
+++  EXPECT_TRUE(info.features.half);
+++  EXPECT_TRUE(info.features.thumb);
+++  EXPECT_FALSE(info.features._26bit);
+++  EXPECT_TRUE(info.features.fastmult);
+++  EXPECT_FALSE(info.features.fpa);
+++  EXPECT_TRUE(info.features.vfp);
+++  EXPECT_TRUE(info.features.edsp);
+++  EXPECT_FALSE(info.features.java);
+++  EXPECT_FALSE(info.features.iwmmxt);
+++  EXPECT_FALSE(info.features.crunch);
+++  EXPECT_FALSE(info.features.thumbee);
+++  EXPECT_TRUE(info.features.neon);
+++  EXPECT_TRUE(info.features.vfpv3);
+++  EXPECT_FALSE(info.features.vfpv3d16);
+++  EXPECT_TRUE(info.features.tls);
+++  EXPECT_FALSE(info.features.vfpv4);
+++  EXPECT_FALSE(info.features.idiva);
+++  EXPECT_FALSE(info.features.idivt);
+++  EXPECT_TRUE(info.features.vfpd32);
+++  EXPECT_FALSE(info.features.lpae);
+++  EXPECT_FALSE(info.features.evtstrm);
+++  EXPECT_FALSE(info.features.aes);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++  EXPECT_FALSE(info.features.crc32);
+++}
+++
+++// Android test-case
+++// http://code.google.com/p/android/issues/detail?id=10812
+++TEST(CpuinfoArmTest, InvalidArmv7) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(Processor       : ARMv6-compatible processor rev 6 (v6l)
+++BogoMIPS        : 199.47
+++Features        : swp half thumb fastmult vfp edsp java
+++CPU implementer : 0x41
+++CPU architecture: 7
+++CPU variant     : 0x0
+++CPU part        : 0xb76
+++CPU revision    : 6
+++
+++Hardware        : SPICA
+++Revision        : 0020
+++Serial          : 33323613546d00ec )");
+++  const auto info = GetArmInfo();
+++  EXPECT_EQ(info.architecture, 6);
+++
+++  EXPECT_TRUE(info.features.swp);
+++  EXPECT_TRUE(info.features.half);
+++  EXPECT_TRUE(info.features.thumb);
+++  EXPECT_FALSE(info.features._26bit);
+++  EXPECT_TRUE(info.features.fastmult);
+++  EXPECT_FALSE(info.features.fpa);
+++  EXPECT_TRUE(info.features.vfp);
+++  EXPECT_TRUE(info.features.edsp);
+++  EXPECT_TRUE(info.features.java);
+++  EXPECT_FALSE(info.features.iwmmxt);
+++  EXPECT_FALSE(info.features.crunch);
+++  EXPECT_FALSE(info.features.thumbee);
+++  EXPECT_FALSE(info.features.neon);
+++  EXPECT_FALSE(info.features.vfpv3);
+++  EXPECT_FALSE(info.features.vfpv3d16);
+++  EXPECT_FALSE(info.features.tls);
+++  EXPECT_FALSE(info.features.vfpv4);
+++  EXPECT_FALSE(info.features.idiva);
+++  EXPECT_FALSE(info.features.idivt);
+++  EXPECT_FALSE(info.features.vfpd32);
+++  EXPECT_FALSE(info.features.lpae);
+++  EXPECT_FALSE(info.features.evtstrm);
+++  EXPECT_FALSE(info.features.aes);
+++  EXPECT_FALSE(info.features.pmull);
+++  EXPECT_FALSE(info.features.sha1);
+++  EXPECT_FALSE(info.features.sha2);
+++  EXPECT_FALSE(info.features.crc32);
+++}
+++
+++// Android test-case
+++// https://crbug.com/341598.
+++TEST(CpuinfoArmTest, InvalidNeon) {
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(Processor: ARMv7 Processory rev 0 (v71)
+++processor: 0
+++BogoMIPS: 13.50
+++
+++Processor: 1
+++BogoMIPS: 13.50
+++
+++Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
+++CPU implementer : 0x51
+++CPU architecture: 7
+++CPU variant: 0x1
+++CPU part: 0x04d
+++CPU revision: 0
+++
+++Hardware: SAMSUNG M2
+++Revision: 0010
+++Serial: 00001e030000354e)");
+++  const auto info = GetArmInfo();
+++  EXPECT_TRUE(info.features.swp);
+++  EXPECT_FALSE(info.features.neon);
+++}
+++
+++// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
+++// support.
+++TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(CPU implementer   : 0x51
+++CPU architecture: 7
+++CPU variant  : 0x0
+++CPU part     : 0x6f
+++CPU revision : 2)");
+++  const auto info = GetArmInfo();
+++  EXPECT_TRUE(info.features.idiva);
+++  EXPECT_TRUE(info.features.idivt);
+++
+++  EXPECT_EQ(GetArmCpuId(&info), 0x510006f2);
+++}
+++
+++// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
+++// support.
+++TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(CPU implementer   : 0x51
+++CPU architecture: 7
+++CPU variant  : 0x0
+++CPU part     : 0x6f
+++CPU revision : 3)");
+++  const auto info = GetArmInfo();
+++  EXPECT_TRUE(info.features.idiva);
+++  EXPECT_TRUE(info.features.idivt);
+++
+++  EXPECT_EQ(GetArmCpuId(&info), 0x510006f3);
+++}
+++
+++// The emulator-specific Android 4.2 kernel fails to report support for the
+++// 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual
+++// CPU implemented by the emulator.
+++TEST(CpuinfoArmTest, EmulatorSpecificIdiv) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(Processor : ARMv7 Processor rev 0 (v7l)
+++BogoMIPS     : 629.14
+++Features     : swp half thumb fastmult vfp edsp neon vfpv3
+++CPU implementer      : 0x41
+++CPU architecture: 7
+++CPU variant  : 0x0
+++CPU part     : 0xc08
+++CPU revision : 0
+++
+++Hardware     : Goldfish
+++Revision     : 0000
+++Serial               : 0000000000000000)");
+++  const auto info = GetArmInfo();
+++  EXPECT_TRUE(info.features.idiva);
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d73405822c0e6cf3061a7d4ac6970d6b2fedc1e0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,126 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_mips.h"
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++#include "hwcaps_for_testing.h"
+++#include "internal/stack_line_reader.h"
+++#include "internal/string_view.h"
+++
+++namespace cpu_features {
+++
+++namespace {
+++
+++void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
+++
+++TEST(CpuinfoMipsTest, FromHardwareCapBoth) {
+++  SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetMipsInfo();
+++  EXPECT_TRUE(info.features.msa);
+++  EXPECT_FALSE(info.features.eva);
+++  EXPECT_TRUE(info.features.r6);
+++}
+++
+++TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) {
+++  SetHardwareCapabilities(MIPS_HWCAP_MSA, 0);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetMipsInfo();
+++  EXPECT_TRUE(info.features.msa);
+++  EXPECT_FALSE(info.features.eva);
+++}
+++
+++TEST(CpuinfoMipsTest, Ci40) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0)
+++machine : IMG Marduk – Ci40 with cc2520
+++processor : 0
+++cpu model : MIPS interAptiv (multi) V2.0 FPU V0.0
+++BogoMIPS : 363.72
+++wait instruction : yes
+++microsecond timers : yes
+++tlb_entries : 64
+++extra interrupt vector : yes
+++hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
+++isa : mips1 mips2 mips32r1 mips32r2
+++ASEs implemented : mips16 dsp mt eva
+++shadow register sets : 1
+++kscratch registers : 0
+++package : 0
+++core : 0
+++VCED exceptions : not available
+++VCEI exceptions : not available
+++VPE : 0
+++)");
+++  const auto info = GetMipsInfo();
+++  EXPECT_FALSE(info.features.msa);
+++  EXPECT_TRUE(info.features.eva);
+++}
+++
+++TEST(CpuinfoMipsTest, AR7161) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(system type             : Atheros AR7161 rev 2
+++machine                 : NETGEAR WNDR3700/WNDR3800/WNDRMAC
+++processor               : 0
+++cpu model               : MIPS 24Kc V7.4
+++BogoMIPS                : 452.19
+++wait instruction        : yes
+++microsecond timers      : yes
+++tlb_entries             : 16
+++extra interrupt vector  : yes
+++hardware watchpoint     : yes, count: 4, address/irw mask: [0x0000, 0x0f98, 0x0f78, 0x0df8]
+++ASEs implemented        : mips16
+++shadow register sets    : 1
+++kscratch registers      : 0
+++core                    : 0
+++VCED exceptions         : not available
+++VCEI exceptions         : not available
+++)");
+++  const auto info = GetMipsInfo();
+++  EXPECT_FALSE(info.features.msa);
+++  EXPECT_FALSE(info.features.eva);
+++}
+++
+++TEST(CpuinfoMipsTest, Goldfish) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(system type              : MIPS-Goldfish
+++Hardware             : goldfish
+++Revison              : 1
+++processor            : 0
+++cpu model            : MIPS 24Kc V0.0  FPU V0.0
+++BogoMIPS             : 1042.02
+++wait instruction     : yes
+++microsecond timers   : yes
+++tlb_entries          : 16
+++extra interrupt vector       : yes
+++hardware watchpoint  : yes, count: 1, address/irw mask: [0x0ff8]
+++ASEs implemented     :
+++shadow register sets : 1
+++core                 : 0
+++VCED exceptions              : not available
+++VCEI exceptions              : not available
+++)");
+++  const auto info = GetMipsInfo();
+++  EXPECT_FALSE(info.features.msa);
+++  EXPECT_FALSE(info.features.eva);
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8f0cb658b89ab0fc7fd22334803499b9421439b6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,119 @@@@
+++// Copyright 2018 IBM.
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_ppc.h"
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++#include "hwcaps_for_testing.h"
+++#include "internal/string_view.h"
+++
+++namespace cpu_features {
+++namespace {
+++
+++void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
+++
+++TEST(CpustringsPPCTest, FromHardwareCap) {
+++  SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX,
+++                          PPC_FEATURE2_ARCH_3_00);
+++  GetEmptyFilesystem();  // disabling /proc/cpuinfo
+++  const auto info = GetPPCInfo();
+++  EXPECT_TRUE(info.features.fpu);
+++  EXPECT_FALSE(info.features.mmu);
+++  EXPECT_TRUE(info.features.vsx);
+++  EXPECT_TRUE(info.features.arch300);
+++  EXPECT_FALSE(info.features.power4);
+++  EXPECT_FALSE(info.features.altivec);
+++  EXPECT_FALSE(info.features.vcrypto);
+++  EXPECT_FALSE(info.features.htm);
+++}
+++
+++TEST(CpustringsPPCTest, Blade) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(processor       : 14
+++cpu             : POWER7 (architected), altivec supported
+++clock           : 3000.000000MHz
+++revision        : 2.1 (pvr 003f 0201)
+++
+++processor       : 15
+++cpu             : POWER7 (architected), altivec supported
+++clock           : 3000.000000MHz
+++revision        : 2.1 (pvr 003f 0201)
+++
+++timebase        : 512000000
+++platform        : pSeries
+++model           : IBM,8406-70Y
+++machine         : CHRP IBM,8406-70Y)");
+++  SetPlatformTypes("power7", "power8");
+++  const auto strings = GetPPCPlatformStrings();
+++  ASSERT_STREQ(strings.platform, "pSeries");
+++  ASSERT_STREQ(strings.model, "IBM,8406-70Y");
+++  ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y");
+++  ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported");
+++  ASSERT_STREQ(strings.type.platform, "power7");
+++  ASSERT_STREQ(strings.type.base_platform, "power8");
+++}
+++
+++TEST(CpustringsPPCTest, Firestone) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(processor       : 126
+++cpu             : POWER8 (raw), altivec supported
+++clock           : 2061.000000MHz
+++revision        : 2.0 (pvr 004d 0200)
+++
+++processor       : 127
+++cpu             : POWER8 (raw), altivec supported
+++clock           : 2061.000000MHz
+++revision        : 2.0 (pvr 004d 0200)
+++
+++timebase        : 512000000
+++platform        : PowerNV
+++model           : 8335-GTA
+++machine         : PowerNV 8335-GTA
+++firmware        : OPAL v3)");
+++  const auto strings = GetPPCPlatformStrings();
+++  ASSERT_STREQ(strings.platform, "PowerNV");
+++  ASSERT_STREQ(strings.model, "8335-GTA");
+++  ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA");
+++  ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported");
+++}
+++
+++TEST(CpustringsPPCTest, w8) {
+++  DisableHardwareCapabilities();
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo",
+++                R"(processor       : 143
+++cpu             : POWER9, altivec supported
+++clock           : 2300.000000MHz
+++revision        : 2.2 (pvr 004e 1202)
+++
+++timebase        : 512000000
+++platform        : PowerNV
+++model           : 0000000000000000
+++machine         : PowerNV 0000000000000000
+++firmware        : OPAL
+++MMU             : Radix)");
+++  const auto strings = GetPPCPlatformStrings();
+++  ASSERT_STREQ(strings.platform, "PowerNV");
+++  ASSERT_STREQ(strings.model, "0000000000000000");
+++  ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000");
+++  ASSERT_STREQ(strings.cpu, "POWER9, altivec supported");
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..636d0f9a8043a0bb4b4aac55c223f4fa74c6a8c6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,533 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "cpuinfo_x86.h"
+++
+++#include <cassert>
+++#include <cstdio>
+++#include <map>
+++#include <set>
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++#include <windows.h>  // IsProcessorFeaturePresent
+++#endif                // CPU_FEATURES_OS_WINDOWS
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++#include "internal/cpuid_x86.h"
+++
+++namespace cpu_features {
+++
+++class FakeCpu {
+++ public:
+++  Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const {
+++    const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
+++    if (itr != cpuid_leaves_.end()) {
+++      return itr->second;
+++    }
+++    return {0, 0, 0, 0};
+++  }
+++
+++  uint32_t GetXCR0Eax() const { return xcr0_eax_; }
+++
+++  void SetLeaves(std::map<std::pair<uint32_t, int>, Leaf> configuration) {
+++    cpuid_leaves_ = std::move(configuration);
+++  }
+++
+++  void SetOsBackupsExtendedRegisters(bool os_backups_extended_registers) {
+++    xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
+++  }
+++
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++  bool GetDarwinSysCtlByName(std::string name) const {
+++    return darwin_sysctlbyname_.count(name);
+++  }
+++
+++  void SetDarwinSysCtlByName(std::string name) {
+++    darwin_sysctlbyname_.insert(name);
+++  }
+++#endif  // CPU_FEATURES_OS_DARWIN
+++
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+++    return windows_isprocessorfeaturepresent_.count(ProcessorFeature);
+++  }
+++
+++  void SetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+++    windows_isprocessorfeaturepresent_.insert(ProcessorFeature);
+++  }
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++
+++ private:
+++  std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++  std::set<std::string> darwin_sysctlbyname_;
+++#endif  // CPU_FEATURES_OS_DARWIN
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  std::set<DWORD> windows_isprocessorfeaturepresent_;
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++  uint32_t xcr0_eax_;
+++};
+++
+++FakeCpu* g_fake_cpu = nullptr;
+++
+++extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+++  return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
+++}
+++
+++extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
+++
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++extern "C" bool GetDarwinSysCtlByName(const char* name) {
+++  return g_fake_cpu->GetDarwinSysCtlByName(name);
+++}
+++#endif  // CPU_FEATURES_OS_DARWIN
+++
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+++  return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature);
+++}
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++
+++namespace {
+++
+++class CpuidX86Test : public ::testing::Test {
+++ protected:
+++  void SetUp() override { g_fake_cpu = new FakeCpu(); }
+++  void TearDown() override { delete g_fake_cpu; }
+++};
+++
+++TEST_F(CpuidX86Test, SandyBridge) {
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(true);
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++  });
+++  const auto info = GetX86Info();
+++  EXPECT_STREQ(info.vendor, "GenuineIntel");
+++  EXPECT_EQ(info.family, 0x06);
+++  EXPECT_EQ(info.model, 0x02A);
+++  EXPECT_EQ(info.stepping, 0x06);
+++  // Leaf 7 is zeroed out so none of the Leaf 7 flags are set.
+++  const auto features = info.features;
+++  EXPECT_FALSE(features.erms);
+++  EXPECT_FALSE(features.avx2);
+++  EXPECT_FALSE(features.avx512f);
+++  EXPECT_FALSE(features.avx512cd);
+++  EXPECT_FALSE(features.avx512er);
+++  EXPECT_FALSE(features.avx512pf);
+++  EXPECT_FALSE(features.avx512bw);
+++  EXPECT_FALSE(features.avx512dq);
+++  EXPECT_FALSE(features.avx512vl);
+++  EXPECT_FALSE(features.avx512ifma);
+++  EXPECT_FALSE(features.avx512vbmi);
+++  EXPECT_FALSE(features.avx512vbmi2);
+++  EXPECT_FALSE(features.avx512vnni);
+++  EXPECT_FALSE(features.avx512bitalg);
+++  EXPECT_FALSE(features.avx512vpopcntdq);
+++  EXPECT_FALSE(features.avx512_4vnniw);
+++  EXPECT_FALSE(features.avx512_4fmaps);
+++  // All old cpu features should be set.
+++  EXPECT_TRUE(features.aes);
+++  EXPECT_TRUE(features.ssse3);
+++  EXPECT_TRUE(features.sse4_1);
+++  EXPECT_TRUE(features.sse4_2);
+++  EXPECT_TRUE(features.avx);
+++  EXPECT_FALSE(features.sha);
+++  EXPECT_TRUE(features.popcnt);
+++  EXPECT_FALSE(features.movbe);
+++  EXPECT_FALSE(features.rdrnd);
+++}
+++
+++const int KiB = 1024;
+++const int MiB = 1024 * KiB;
+++
+++TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) {
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++  });
+++  // avx is disabled if os does not support backing up ymm registers.
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+++  EXPECT_FALSE(GetX86Info().features.avx);
+++  // avx is disabled if os does not support backing up ymm registers.
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(true);
+++  EXPECT_TRUE(GetX86Info().features.avx);
+++}
+++
+++TEST_F(CpuidX86Test, SkyLake) {
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(true);
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
+++  });
+++  const auto info = GetX86Info();
+++  EXPECT_STREQ(info.vendor, "GenuineIntel");
+++  EXPECT_EQ(info.family, 0x06);
+++  EXPECT_EQ(info.model, 0x04E);
+++  EXPECT_EQ(info.stepping, 0x03);
+++  EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
+++}
+++
+++TEST_F(CpuidX86Test, Branding) {
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
+++      {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
+++      {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
+++      {{0x80000004, 0}, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}},
+++  });
+++  char brand_string[49];
+++  FillX86BrandString(brand_string);
+++  EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
+++}
+++
+++TEST_F(CpuidX86Test, KabyLakeCache) {
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+++      {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
+++      {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}},
+++      {{0x00000004, 2}, Leaf{0x1C004143, 0x00C0003F, 0x000003FF, 0x00000000}},
+++      {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000002}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
+++      {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
+++      {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
+++  });
+++  const auto info = GetX86CacheInfo();
+++  EXPECT_EQ(info.size, 4);
+++  EXPECT_EQ(info.levels[0].level, 1);
+++  EXPECT_EQ(info.levels[0].cache_type, 1);
+++  EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
+++  EXPECT_EQ(info.levels[0].ways, 8);
+++  EXPECT_EQ(info.levels[0].line_size, 64);
+++  EXPECT_EQ(info.levels[0].tlb_entries, 64);
+++  EXPECT_EQ(info.levels[0].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[1].level, 1);
+++  EXPECT_EQ(info.levels[1].cache_type, 2);
+++  EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
+++  EXPECT_EQ(info.levels[1].ways, 8);
+++  EXPECT_EQ(info.levels[1].line_size, 64);
+++  EXPECT_EQ(info.levels[1].tlb_entries, 64);
+++  EXPECT_EQ(info.levels[1].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[2].level, 2);
+++  EXPECT_EQ(info.levels[2].cache_type, 3);
+++  EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
+++  EXPECT_EQ(info.levels[2].ways, 4);
+++  EXPECT_EQ(info.levels[2].line_size, 64);
+++  EXPECT_EQ(info.levels[2].tlb_entries, 1024);
+++  EXPECT_EQ(info.levels[2].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[3].level, 3);
+++  EXPECT_EQ(info.levels[3].cache_type, 3);
+++  EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
+++  EXPECT_EQ(info.levels[3].ways, 12);
+++  EXPECT_EQ(info.levels[3].line_size, 64);
+++  EXPECT_EQ(info.levels[3].tlb_entries, 8192);
+++  EXPECT_EQ(info.levels[3].partitioning, 1);
+++}
+++
+++TEST_F(CpuidX86Test, HSWCache) {
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+++      {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
+++      {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}},
+++      {{0x00000004, 2}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
+++      {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000006}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
+++      {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
+++      {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
+++  });
+++  const auto info = GetX86CacheInfo();
+++  EXPECT_EQ(info.size, 4);
+++  EXPECT_EQ(info.levels[0].level, 1);
+++  EXPECT_EQ(info.levels[0].cache_type, 1);
+++  EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
+++  EXPECT_EQ(info.levels[0].ways, 8);
+++  EXPECT_EQ(info.levels[0].line_size, 64);
+++  EXPECT_EQ(info.levels[0].tlb_entries, 64);
+++  EXPECT_EQ(info.levels[0].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[1].level, 1);
+++  EXPECT_EQ(info.levels[1].cache_type, 2);
+++  EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
+++  EXPECT_EQ(info.levels[1].ways, 8);
+++  EXPECT_EQ(info.levels[1].line_size, 64);
+++  EXPECT_EQ(info.levels[1].tlb_entries, 64);
+++  EXPECT_EQ(info.levels[1].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[2].level, 2);
+++  EXPECT_EQ(info.levels[2].cache_type, 3);
+++  EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
+++  EXPECT_EQ(info.levels[2].ways, 8);
+++  EXPECT_EQ(info.levels[2].line_size, 64);
+++  EXPECT_EQ(info.levels[2].tlb_entries, 512);
+++  EXPECT_EQ(info.levels[2].partitioning, 1);
+++
+++  EXPECT_EQ(info.levels[3].level, 3);
+++  EXPECT_EQ(info.levels[3].cache_type, 3);
+++  EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
+++  EXPECT_EQ(info.levels[3].ways, 12);
+++  EXPECT_EQ(info.levels[3].line_size, 64);
+++  EXPECT_EQ(info.levels[3].tlb_entries, 8192);
+++  EXPECT_EQ(info.levels[3].partitioning, 1);
+++}
+++
+++// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
+++TEST_F(CpuidX86Test, AMD_K15) {
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
+++      {{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
+++      {{0x80000001, 0}, Leaf{0x00630F81, 0x10000000, 0x0FEBBFFF, 0x2FD3FBFF}},
+++      {{0x80000002, 0}, Leaf{0x20444D41, 0x372D3841, 0x4B303736, 0x64615220}},
+++      {{0x80000003, 0}, Leaf{0x206E6F65, 0x202C3752, 0x43203031, 0x75706D6F}},
+++      {{0x80000004, 0}, Leaf{0x43206574, 0x7365726F, 0x2B433420, 0x00204736}},
+++      {{0x80000005, 0}, Leaf{0xFF40FF18, 0xFF40FF30, 0x10040140, 0x60030140}},
+++  });
+++  const auto info = GetX86Info();
+++
+++  EXPECT_STREQ(info.vendor, "AuthenticAMD");
+++  EXPECT_EQ(info.family, 0x15);
+++  EXPECT_EQ(info.model, 0x38);
+++  EXPECT_EQ(info.stepping, 0x01);
+++  EXPECT_EQ(GetX86Microarchitecture(&info),
+++            X86Microarchitecture::AMD_BULLDOZER);
+++
+++  char brand_string[49];
+++  FillX86BrandString(brand_string);
+++  EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
+++}
+++
+++// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt
+++TEST_F(CpuidX86Test, Nehalem) {
+++  // Pre AVX cpus don't have xsave
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_XMMI_INSTRUCTIONS_AVAILABLE);
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_SSE3_INSTRUCTIONS_AVAILABLE);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
+++#endif  // CPU_FEATURES_OS_DARWIN
+++#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(processor       :
+++flags           : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
+++)");
+++#endif  // CPU_FEATURES_OS_LINUX_OR_ANDROID
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
+++      {{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
+++      {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
+++      {{0x00000004, 0}, Leaf{0x1C004122, 0x00C0003F, 0x0000007F, 0x00000000}},
+++      {{0x00000004, 0}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
+++      {{0x00000004, 0}, Leaf{0x1C03C163, 0x03C0003F, 0x00000FFF, 0x00000002}},
+++      {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00021120}},
+++      {{0x00000006, 0}, Leaf{0x00000001, 0x00000002, 0x00000001, 0x00000000}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x0000000A, 0}, Leaf{0x07300403, 0x00000000, 0x00000000, 0x00000603}},
+++      {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
+++      {{0x0000000B, 0}, Leaf{0x00000004, 0x00000002, 0x00000201, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x28100000}},
+++      {{0x80000002, 0}, Leaf{0x756E6547, 0x20656E69, 0x65746E49, 0x2952286C}},
+++      {{0x80000003, 0}, Leaf{0x55504320, 0x20202020, 0x20202020, 0x40202020}},
+++      {{0x80000004, 0}, Leaf{0x30303020, 0x20402030, 0x37382E31, 0x007A4847}},
+++      {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x01006040, 0x00000000}},
+++      {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
+++      {{0x80000008, 0}, Leaf{0x00003028, 0x00000000, 0x00000000, 0x00000000}},
+++  });
+++  const auto info = GetX86Info();
+++
+++  EXPECT_STREQ(info.vendor, "GenuineIntel");
+++  EXPECT_EQ(info.family, 0x06);
+++  EXPECT_EQ(info.model, 0x1A);
+++  EXPECT_EQ(info.stepping, 0x02);
+++  EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM);
+++
+++  char brand_string[49];
+++  FillX86BrandString(brand_string);
+++  EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU           @ 0000 @ 1.87GHz");
+++
+++  EXPECT_TRUE(info.features.sse);
+++  EXPECT_TRUE(info.features.sse2);
+++  EXPECT_TRUE(info.features.sse3);
+++#ifndef CPU_FEATURES_OS_WINDOWS
+++  // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+++  // feature detection > sse3.
+++  EXPECT_TRUE(info.features.ssse3);
+++  EXPECT_TRUE(info.features.sse4_1);
+++  EXPECT_TRUE(info.features.sse4_2);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++}
+++
+++// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
+++TEST_F(CpuidX86Test, Atom) {
+++  // Pre AVX cpus don't have xsave
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_XMMI_INSTRUCTIONS_AVAILABLE);
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_SSE3_INSTRUCTIONS_AVAILABLE);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
+++#endif  // CPU_FEATURES_OS_DARWIN
+++#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(
+++flags           : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
+++)");
+++#endif  // CPU_FEATURES_OS_LINUX_OR_ANDROID
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
+++      {{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
+++      {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x00000004, 0}, Leaf{0x1C000121, 0x0140003F, 0x0000003F, 0x00000001}},
+++      {{0x00000004, 1}, Leaf{0x1C000122, 0x01C0003F, 0x0000003F, 0x00000001}},
+++      {{0x00000004, 2}, Leaf{0x1C00C143, 0x03C0003F, 0x000003FF, 0x00000001}},
+++      {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x33000020}},
+++      {{0x00000006, 0}, Leaf{0x00000005, 0x00000002, 0x00000009, 0x00000000}},
+++      {{0x00000007, 0}, Leaf{0x00000000, 0x00002282, 0x00000000, 0x00000000}},
+++      {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x0000000A, 0}, Leaf{0x07280203, 0x00000000, 0x00000000, 0x00004503}},
+++      {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
+++      {{0x0000000B, 1}, Leaf{0x00000004, 0x00000004, 0x00000201, 0x00000000}},
+++      {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000101, 0x28100000}},
+++      {{0x80000002, 0}, Leaf{0x20202020, 0x6E492020, 0x286C6574, 0x43202952}},
+++      {{0x80000003, 0}, Leaf{0x72656C65, 0x52286E6F, 0x50432029, 0x4A202055}},
+++      {{0x80000004, 0}, Leaf{0x30303931, 0x20402020, 0x39392E31, 0x007A4847}},
+++      {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+++      {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x04008040, 0x00000000}},
+++      {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
+++      {{0x80000008, 0}, Leaf{0x00003024, 0x00000000, 0x00000000, 0x00000000}},
+++  });
+++  const auto info = GetX86Info();
+++
+++  EXPECT_STREQ(info.vendor, "GenuineIntel");
+++  EXPECT_EQ(info.family, 0x06);
+++  EXPECT_EQ(info.model, 0x37);
+++  EXPECT_EQ(info.stepping, 0x03);
+++  EXPECT_EQ(GetX86Microarchitecture(&info),
+++            X86Microarchitecture::INTEL_ATOM_SMT);
+++
+++  char brand_string[49];
+++  FillX86BrandString(brand_string);
+++  EXPECT_STREQ(brand_string, "      Intel(R) Celeron(R) CPU  J1900  @ 1.99GHz");
+++
+++  EXPECT_TRUE(info.features.sse);
+++  EXPECT_TRUE(info.features.sse2);
+++  EXPECT_TRUE(info.features.sse3);
+++#ifndef CPU_FEATURES_OS_WINDOWS
+++  // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+++  // feature detection > sse3.
+++  EXPECT_TRUE(info.features.ssse3);
+++  EXPECT_TRUE(info.features.sse4_1);
+++  EXPECT_TRUE(info.features.sse4_2);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++}
+++
+++// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
+++TEST_F(CpuidX86Test, P3) {
+++  // Pre AVX cpus don't have xsave
+++  g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+++#if defined(CPU_FEATURES_OS_WINDOWS)
+++  g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+++      PF_XMMI_INSTRUCTIONS_AVAILABLE);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++#if defined(CPU_FEATURES_OS_DARWIN)
+++  g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+++#endif  // CPU_FEATURES_OS_DARWIN
+++#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+++  auto& fs = GetEmptyFilesystem();
+++  fs.CreateFile("/proc/cpuinfo", R"(
+++flags           : fpu mmx sse
+++)");
+++#endif  // CPU_FEATURES_OS_LINUX_OR_ANDROID
+++  g_fake_cpu->SetLeaves({
+++      {{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
+++      {{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
+++      {{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
+++      {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x4CECC782, 0x00006778}},
+++  });
+++  const auto info = GetX86Info();
+++
+++  EXPECT_STREQ(info.vendor, "GenuineIntel");
+++  EXPECT_EQ(info.family, 0x06);
+++  EXPECT_EQ(info.model, 0x07);
+++  EXPECT_EQ(info.stepping, 0x03);
+++  EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN);
+++
+++  char brand_string[49];
+++  FillX86BrandString(brand_string);
+++  EXPECT_STREQ(brand_string, "");
+++
+++  EXPECT_TRUE(info.features.mmx);
+++  EXPECT_TRUE(info.features.sse);
+++  EXPECT_FALSE(info.features.sse2);
+++  EXPECT_FALSE(info.features.sse3);
+++#ifndef CPU_FEATURES_OS_WINDOWS
+++  // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+++  // feature detection > sse3.
+++  EXPECT_FALSE(info.features.ssse3);
+++  EXPECT_FALSE(info.features.sse4_1);
+++  EXPECT_FALSE(info.features.sse4_2);
+++#endif  // CPU_FEATURES_OS_WINDOWS
+++}
+++
+++// TODO(user): test what happens when xsave/osxsave are not present.
+++// TODO(user): test what happens when xmm/ymm/zmm os support are not
+++// present.
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..648a53e39eb3ee33a650a06bebddf0948ee6a32d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,103 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "filesystem_for_testing.h"
+++
+++#include <cassert>
+++#include <climits>
+++#include <cstdio>
+++#include <cstring>
+++#include <utility>
+++
+++namespace cpu_features {
+++
+++FakeFile::FakeFile(int file_descriptor, const char* content)
+++    : file_descriptor_(file_descriptor), content_(content) {}
+++
+++FakeFile::~FakeFile() { assert(!opened_); }
+++
+++void FakeFile::Open() {
+++  assert(!opened_);
+++  opened_ = true;
+++}
+++
+++void FakeFile::Close() {
+++  assert(opened_);
+++  opened_ = false;
+++}
+++
+++int FakeFile::Read(int fd, void* buf, size_t count) {
+++  assert(count < INT_MAX);
+++  assert(fd == file_descriptor_);
+++  const size_t remainder = content_.size() - head_index_;
+++  const size_t read = count > remainder ? remainder : count;
+++  memcpy(buf, content_.data() + head_index_, read);
+++  head_index_ += read;
+++  assert(read < INT_MAX);
+++  return (int)read;
+++}
+++
+++void FakeFilesystem::Reset() { files_.clear(); }
+++
+++FakeFile* FakeFilesystem::CreateFile(const std::string& filename,
+++                                     const char* content) {
+++  auto& file = files_[filename];
+++  file =
+++      std::unique_ptr<FakeFile>(new FakeFile(next_file_descriptor_++, content));
+++  return file.get();
+++}
+++
+++FakeFile* FakeFilesystem::FindFileOrNull(const std::string& filename) const {
+++  const auto itr = files_.find(filename);
+++  return itr == files_.end() ? nullptr : itr->second.get();
+++}
+++
+++FakeFile* FakeFilesystem::FindFileOrDie(const int file_descriptor) const {
+++  for (const auto& filename_file_pair : files_) {
+++    FakeFile* const file_ptr = filename_file_pair.second.get();
+++    if (file_ptr->GetFileDescriptor() == file_descriptor) {
+++      return file_ptr;
+++    }
+++  }
+++  assert(false);
+++  return nullptr;
+++}
+++
+++static FakeFilesystem* kFilesystem = new FakeFilesystem();
+++
+++FakeFilesystem& GetEmptyFilesystem() {
+++  kFilesystem->Reset();
+++  return *kFilesystem;
+++}
+++
+++extern "C" int CpuFeatures_OpenFile(const char* filename) {
+++  auto* const file = kFilesystem->FindFileOrNull(filename);
+++  if (file) {
+++    file->Open();
+++    return file->GetFileDescriptor();
+++  }
+++  return -1;
+++}
+++
+++extern "C" void CpuFeatures_CloseFile(int file_descriptor) {
+++  kFilesystem->FindFileOrDie(file_descriptor)->Close();
+++}
+++
+++extern "C" int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
+++                                    size_t buffer_size) {
+++  return kFilesystem->FindFileOrDie(file_descriptor)
+++      ->Read(file_descriptor, buffer, buffer_size);
+++}
+++
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ef717fdf55a3811e780cd8b2a6b9c6d3388250fe
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,61 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++// Implements a fake filesystem, useful for tests.
+++#ifndef CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
+++#define CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
+++
+++#include <memory>
+++#include <string>
+++#include <unordered_map>
+++
+++#include "internal/filesystem.h"
+++
+++namespace cpu_features {
+++
+++class FakeFile {
+++ public:
+++  explicit FakeFile(int file_descriptor, const char* content);
+++  ~FakeFile();
+++
+++  void Open();
+++  void Close();
+++  int Read(int fd, void* buf, size_t count);
+++
+++  int GetFileDescriptor() const { return file_descriptor_; }
+++
+++ private:
+++  const int file_descriptor_;
+++  const std::string content_;
+++  bool opened_ = false;
+++  size_t head_index_ = 0;
+++};
+++
+++class FakeFilesystem {
+++ public:
+++  void Reset();
+++  FakeFile* CreateFile(const std::string& filename, const char* content);
+++  FakeFile* FindFileOrDie(const int file_descriptor) const;
+++  FakeFile* FindFileOrNull(const std::string& filename) const;
+++
+++ private:
+++  int next_file_descriptor_ = 0;
+++  std::unordered_map<std::string, std::unique_ptr<FakeFile>> files_;
+++};
+++
+++FakeFilesystem& GetEmptyFilesystem();
+++
+++}  // namespace cpu_features
+++
+++#endif  // CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a8086a03ae5c39b9bc15e374a24728ef688db2d8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,46 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "hwcaps_for_testing.h"
+++
+++#include <string.h>
+++
+++#include "internal/string_view.h"
+++
+++namespace cpu_features {
+++
+++namespace {
+++static auto* const g_hardware_capabilities = new HardwareCapabilities();
+++static auto* const g_platform_types = new PlatformType();
+++}  // namespace
+++
+++void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) {
+++  g_hardware_capabilities->hwcaps = hwcaps;
+++  g_hardware_capabilities->hwcaps2 = hwcaps2;
+++}
+++
+++HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
+++  return *g_hardware_capabilities;
+++}
+++
+++void SetPlatformTypes(const char* platform, const char* base_platform) {
+++  CpuFeatures_StringView_CopyString(str(platform), g_platform_types->platform,
+++                                    sizeof(g_platform_types->platform));
+++  CpuFeatures_StringView_CopyString(str(base_platform),
+++                                    g_platform_types->base_platform,
+++                                    sizeof(g_platform_types->base_platform));
+++}
+++
+++PlatformType CpuFeatures_GetPlatformType(void) { return *g_platform_types; }
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bcab82edfe40871468b10f79d4d97fb2e1bfac1e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,27 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
+++#define CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
+++
+++#include "internal/hwcaps.h"
+++
+++namespace cpu_features {
+++
+++void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2);
+++void SetPlatformTypes(const char *platform, const char *base_platform);
+++
+++}  // namespace cpu_features
+++
+++#endif  // CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9ac5388d167adf3f0753e4150bbe5062ab8caa74
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,132 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/stack_line_reader.h"
+++
+++#include "filesystem_for_testing.h"
+++#include "gtest/gtest.h"
+++
+++namespace cpu_features {
+++
+++bool operator==(const StringView& a, const StringView& b) {
+++  return CpuFeatures_StringView_IsEquals(a, b);
+++}
+++
+++namespace {
+++
+++std::string ToString(StringView view) { return {view.ptr, view.size}; }
+++
+++TEST(StackLineReaderTest, Empty) {
+++  auto& fs = GetEmptyFilesystem();
+++  auto* file = fs.CreateFile("/proc/cpuinfo", "");
+++  StackLineReader reader;
+++  StackLineReader_Initialize(&reader, file->GetFileDescriptor());
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_TRUE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str(""));
+++  }
+++}
+++
+++TEST(StackLineReaderTest, ManySmallLines) {
+++  auto& fs = GetEmptyFilesystem();
+++  auto* file = fs.CreateFile("/proc/cpuinfo", "a\nb\nc");
+++
+++  StackLineReader reader;
+++  StackLineReader_Initialize(&reader, file->GetFileDescriptor());
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("a"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("b"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_TRUE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("c"));
+++  }
+++}
+++
+++TEST(StackLineReaderTest, TruncatedLine) {
+++  auto& fs = GetEmptyFilesystem();
+++  auto* file = fs.CreateFile("/proc/cpuinfo", R"(First
+++Second
+++More than 16 characters, this will be truncated.
+++last)");
+++
+++  StackLineReader reader;
+++  StackLineReader_Initialize(&reader, file->GetFileDescriptor());
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("First"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("Second"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_FALSE(result.full_line);
+++    EXPECT_EQ(result.line, str("More than 16 cha"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_TRUE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str("last"));
+++  }
+++}
+++
+++TEST(StackLineReaderTest, TruncatedLines) {
+++  auto& fs = GetEmptyFilesystem();
+++  auto* file = fs.CreateFile("/proc/cpuinfo", R"(More than 16 characters
+++Another line that is too long)");
+++
+++  StackLineReader reader;
+++  StackLineReader_Initialize(&reader, file->GetFileDescriptor());
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_FALSE(result.full_line);
+++    EXPECT_EQ(result.line, str("More than 16 cha"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_FALSE(result.eof);
+++    EXPECT_FALSE(result.full_line);
+++    EXPECT_EQ(result.line, str("Another line tha"));
+++  }
+++  {
+++    const auto result = StackLineReader_NextLine(&reader);
+++    EXPECT_TRUE(result.eof);
+++    EXPECT_TRUE(result.full_line);
+++    EXPECT_EQ(result.line, str(""));
+++  }
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ca3e023a7ad38f074336d6ba0b91263915625d2f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,192 @@@@
+++// Copyright 2017 Google LLC
+++//
+++// Licensed under the Apache License, Version 2.0 (the "License");
+++// you may not use this file except in compliance with the License.
+++// You may obtain a copy of the License at
+++//
+++//    http://www.apache.org/licenses/LICENSE-2.0
+++//
+++// Unless required by applicable law or agreed to in writing, software
+++// distributed under the License is distributed on an "AS IS" BASIS,
+++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++// See the License for the specific language governing permissions and
+++// limitations under the License.
+++
+++#include "internal/string_view.h"
+++
+++#include "gtest/gtest.h"
+++
+++namespace cpu_features {
+++
+++bool operator==(const StringView& a, const StringView& b) {
+++  return CpuFeatures_StringView_IsEquals(a, b);
+++}
+++
+++namespace {
+++
+++TEST(StringViewTest, Empty) {
+++  EXPECT_EQ(kEmptyStringView.ptr, nullptr);
+++  EXPECT_EQ(kEmptyStringView.size, 0);
+++}
+++
+++TEST(StringViewTest, Build) {
+++  const auto view = str("test");
+++  EXPECT_EQ(view.ptr[0], 't');
+++  EXPECT_EQ(view.size, 4);
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
+++  // Found.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0);
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1);
+++  // Not found.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
+++  // Empty.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(kEmptyStringView, 'z'), -1);
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
+++  // Found.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0);
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4);
+++  // Not found.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
+++  // Empty.
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(kEmptyStringView, str("aa")), -1);
+++  EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("aa"), kEmptyStringView), -1);
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_StartsWith) {
+++  EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
+++  EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test")));
+++  EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st")));
+++  EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est")));
+++  EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
+++  EXPECT_FALSE(
+++      CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
+++  EXPECT_FALSE(
+++      CpuFeatures_StringView_StartsWith(kEmptyStringView, str("test")));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_IsEquals) {
+++  EXPECT_TRUE(
+++      CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
+++  EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
+++  EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
+++  EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test")));
+++  EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
+++  EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
+++  EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a")));
+++  EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa")));
+++  EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
+++  EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_PopFront) {
+++  EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 2), str("st"));
+++  EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 0), str("test"));
+++  EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 4), str(""));
+++  EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_PopBack) {
+++  EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te"));
+++  EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test"));
+++  EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str(""));
+++  EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str(""));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_KeepFront) {
+++  EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te"));
+++  EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str(""));
+++  EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test"));
+++  EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test"));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_Front) {
+++  EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a');
+++  EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a');
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_Back) {
+++  EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e');
+++  EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a');
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) {
+++  EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("  first middle last  ")),
+++            str("first middle last"));
+++  EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last  ")),
+++            str("first middle last"));
+++  EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("  first middle last")),
+++            str("first middle last"));
+++  EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
+++            str("first middle last"));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) {
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794);
+++
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
+++  EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_CopyString) {
+++  char buf[4];
+++  buf[0] = 'X';
+++
+++  // Empty
+++  CpuFeatures_StringView_CopyString(str(""), buf, sizeof(buf));
+++  EXPECT_STREQ(buf, "");
+++
+++  // Less
+++  CpuFeatures_StringView_CopyString(str("a"), buf, sizeof(buf));
+++  EXPECT_STREQ(buf, "a");
+++
+++  // exact
+++  CpuFeatures_StringView_CopyString(str("abc"), buf, sizeof(buf));
+++  EXPECT_STREQ(buf, "abc");
+++
+++  // More
+++  CpuFeatures_StringView_CopyString(str("abcd"), buf, sizeof(buf));
+++  EXPECT_STREQ(buf, "abc");
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_HasWord) {
+++  // Find flags at beginning, middle and end.
+++  EXPECT_TRUE(
+++      CpuFeatures_StringView_HasWord(str("first middle last"), "first"));
+++  EXPECT_TRUE(
+++      CpuFeatures_StringView_HasWord(str("first middle last"), "middle"));
+++  EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last"));
+++  // Do not match partial flags
+++  EXPECT_FALSE(
+++      CpuFeatures_StringView_HasWord(str("first middle last"), "irst"));
+++  EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid"));
+++  EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las"));
+++}
+++
+++TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) {
+++  const StringView line = str(" key :   first middle last   ");
+++  StringView key, value;
+++  EXPECT_TRUE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
+++  EXPECT_EQ(key, str("key"));
+++  EXPECT_EQ(value, str("first middle last"));
+++}
+++
+++TEST(StringViewTest, FailingGetAttributeKeyValue) {
+++  const StringView line = str("key  first middle last");
+++  StringView key, value;
+++  EXPECT_FALSE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
+++}
+++
+++}  // namespace
+++}  // namespace cpu_features
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..45f18a6b4be0558edee56694fa2351a991156ebb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,491 @@@@
+++volk (2.4.0-3) unstable; urgency=medium
+++
+++  * Fix binary-indep build (Closes: #976300)
+++  * Upload to unstable
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 03 Dec 2020 20:43:29 -0500
+++
+++volk (2.4.0-2) experimental; urgency=medium
+++
+++  * Make use of cpu_features a CMake option with sensible defaults per arch
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 30 Nov 2020 16:19:19 -0500
+++
+++volk (2.4.0-1) experimental; urgency=medium
+++
+++  * New upstream release
+++  * cpu_features git submodule packaged as cpu-features source component.
+++  * Upload to experimental for soversion bump
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 22 Nov 2020 12:35:43 -0500
+++
+++volk (2.3.0-3) unstable; urgency=medium
+++
+++  * update to v2.3.0-14-g91e5d07
+++    emit an emms instruction after using the mmx extension
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 30 Jun 2020 19:48:20 -0400
+++
+++volk (2.3.0-2) unstable; urgency=medium
+++
+++  * Upload to unstable
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 11 May 2020 07:26:03 -0400
+++
+++volk (2.3.0-1) experimental; urgency=medium
+++
+++  * New upstream release, to experimental for soversion bump
+++  * Kernels
+++    - volk: accurate exp kernel
+++        - exp: Rename SSE4.1 to SSE2 kernel
+++    - Add 32f_s32f_add_32f kernel
+++        - This kernel adds in vector + scalar functionality
+++    - Fix the broken index max kernels
+++    - Treat the mod_range puppet as such
+++    - Add puppet for power spectral density kernel
+++    - Updated log10 calcs to use faster log2 approach
+++    - fix: Use unaligned load
+++    - divide: Optimize complexmultiplyconjugate
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sat, 09 May 2020 15:42:23 -0400
+++
+++volk (2.2.1-3) unstable; urgency=medium
+++
+++  * update to v2.2.1-34-gd4756c5
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 05 Apr 2020 10:37:46 -0400
+++
+++volk (2.2.1-2) unstable; urgency=medium
+++
+++  * update to v2.2.1-11-gfaf230e
+++  * cmake: Remove the ORC from the VOLK public link interface
+++  * Fix the broken index max kernels
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 27 Mar 2020 21:48:10 -0400
+++
+++volk (2.2.1-1) unstable; urgency=high
+++
+++  * New upstream bugfix release
+++    reason for high urgency:
+++    - Fix loop bound in AVX rotator (only one fixed in 2.2.0-3)
+++    - Fix out-of-bounds read in AVX2 square dist kernel
+++    - Fix length checks in AVX2 index max kernels
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 24 Feb 2020 18:08:05 -0500
+++
+++volk (2.2.0-3) unstable; urgency=high
+++
+++  * Update to v2.2.0-6-g5701f8f
+++    reason for high urgency:
+++    - Fix loop bound in AVX rotator
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 23 Feb 2020 23:49:18 -0500
+++
+++volk (2.2.0-2) unstable; urgency=medium
+++
+++  * Upload to unstable
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 18 Feb 2020 17:56:58 -0500
+++
+++volk (2.2.0-1) experimental; urgency=medium
+++
+++  * New upstream release
+++    - Remove build dependency on python six
+++    - Fixup VolkConfigVersion
+++    - add volk_version.h
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 16 Feb 2020 18:25:20 -0500
+++
+++volk (2.1.0-2) unstable; urgency=medium
+++
+++  * Upload to unstable
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 05 Jan 2020 23:17:57 -0500
+++
+++volk (2.1.0-1) experimental; urgency=medium
+++
+++  * New upstream release
+++    - The AVX FMA rotator bug is fixed
+++    - VOLK offers `volk::vector<>` for C++ to follow RAII
+++    - Use C++17 `std::filesystem`
+++        - This enables VOLK to be built without Boost if available!
+++    - lots of bugfixes
+++    - more optimized kernels, especially more NEON versions
+++  * Upload to experimental for new ABI library package libvolk2.1
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 22 Dec 2019 10:27:36 -0500
+++
+++volk (2.0.0-3) unstable; urgency=medium
+++
+++  * update to v2.0.0-4-gf04a46f
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 14 Nov 2019 22:47:23 -0500
+++
+++volk (2.0.0-2) unstable; urgency=medium
+++
+++  * Upload to unstable
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 12 Aug 2019 22:49:11 -0400
+++
+++volk (2.0.0-1) experimental; urgency=medium
+++
+++  * New upstream release
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 07 Aug 2019 23:31:20 -0400
+++
+++volk (1.4-4) unstable; urgency=medium
+++
+++  * working volk_modtool with Python 3
+++  * build and install libvolk.a
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 29 Oct 2018 01:32:05 -0400
+++
+++volk (1.4-3) unstable; urgency=medium
+++
+++  * update to v1.4-9-g297fefd
+++    Added an AVX protokernel for volk_32fc_x2_32f_square_dist_scalar_mult_32f
+++    fixed a buffer over-read and over-write in
+++     volk_32fc_x2_s32f_square_dist_scalar_mult_32f_a_avx
+++    Fix 32u_reverse_32u for ARM
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sat, 12 May 2018 15:25:04 -0400
+++
+++volk (1.4-2) unstable; urgency=medium
+++
+++  * Upload to unstable, needed by gnuradio (>= 3.7.12.0)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 03 Apr 2018 01:03:19 -0400
+++
+++volk (1.4-1) experimental; urgency=medium
+++
+++  * New upstream release
+++    upstream changelog http://libvolk.org/release-v14.html
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 27 Mar 2018 22:57:42 -0400
+++
+++volk (1.3.1-1) unstable; urgency=medium
+++
+++  * New upstream bugfix release
+++  * Refresh all debian patches for use with git am
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 27 Mar 2018 21:54:29 -0400
+++
+++volk (1.3-3) unstable; urgency=medium
+++
+++  * update to v1.3-23-g0109b2e
+++  * update debian/libvolk1-dev.abi.tar.gz.amd64
+++  * Add breaks/replaces gnuradio (<=3.7.2.1) (LP: #1614235)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 04 Feb 2018 13:12:21 -0500
+++
+++volk (1.3-2) unstable; urgency=medium
+++
+++  * update to v1.3-16-g28b03a9
+++    apps: fix profile update reading end of lines
+++    qa: lower tolerance for 32fc_mag to fix issue #96
+++  * include upstream master patch to sort input files
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 27 Aug 2017 13:44:55 -0400
+++
+++volk (1.3-1) unstable; urgency=medium
+++
+++  * New upstream release
+++  * The index_max kernels were named with the wrong output datatype. To
+++    fix this there are new kernels that return a 32u (int32_t) and the
+++    existing kernels had their signatures changed to return 16u (int16_t).
+++  * The output to stdout and stderr has been shuffled around. There is no
+++    longer a message that prints what VOLK machine is being used and the
+++    warning messages go to stderr rather than stdout.
+++  * The 32fc_index_max kernels previously were only accurate to the SSE
+++    register width (4 points). This was a pretty serious and long-lived
+++    bug that's been fixed and the QA updated appropriately.
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sat, 02 Jul 2016 16:30:47 -0400
+++
+++volk (1.2.2-2) unstable; urgency=medium
+++
+++  * update to v1.2.2-11-g78c8bc4 (to follow gnuradio maint branch)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 19 Jun 2016 14:44:15 -0400
+++
+++volk (1.2.2-1) unstable; urgency=medium
+++
+++  * New upstream release
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 08 Apr 2016 00:12:10 -0400
+++
+++volk (1.2.1-2) unstable; urgency=medium
+++
+++  * Upstream patches:
+++    Fix some CMake complaints
+++    The fix for compilation with cmake 3.5
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 23 Mar 2016 17:47:54 -0400
+++
+++volk (1.2.1-1) unstable; urgency=medium
+++
+++  * New upstream release
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 07 Feb 2016 19:38:32 -0500
+++
+++volk (1.2-1) unstable; urgency=medium
+++
+++  * New upstream release
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 24 Dec 2015 20:28:13 -0500
+++
+++volk (1.1.1-5) experimental; urgency=medium
+++
+++  * update to v1.1.1-22-gef53547 to support gnuradio 3.7.9
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 11 Dec 2015 13:12:55 -0500
+++
+++volk (1.1.1-4) unstable; urgency=medium
+++
+++  * more lintian fixes
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 25 Nov 2015 21:49:58 -0500
+++
+++volk (1.1.1-3) unstable; urgency=medium
+++
+++  * Lintian fixes Pre-Depends
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 19 Nov 2015 21:24:27 -0500
+++
+++volk (1.1.1-2) unstable; urgency=medium
+++
+++  * Note that libvolk1-dev replaces files in gnuradio-dev versions <<3.7.8
+++    (Closes: #802646) again. Thanks Andreas Beckmann.
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 13 Nov 2015 18:45:49 -0500
+++
+++volk (1.1.1-1) unstable; urgency=medium
+++
+++  * New upstream release
+++  * New architectures exist for the AVX2 and FMA ISAs.
+++  * The profiler now generates buffers that are vlen + a tiny amount and
+++    generates random data to fill buffers. This is intended to catch bugs
+++    in protokernels that write beyond num_points.
+++  * Note that libvolk1-dev replaces files in earlier gnuradio-dev versions
+++    (Closes: #802646)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 01 Nov 2015 18:45:43 -0500
+++
+++volk (1.1-4) unstable; urgency=medium
+++
+++  * update to v1.1-12-g264addc
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Tue, 29 Sep 2015 23:41:50 -0400
+++
+++volk (1.1-3) unstable; urgency=low
+++
+++  * drop dh_acc to get reproducible builds
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 11 Sep 2015 22:57:06 -0400
+++
+++volk (1.1-2) unstable; urgency=low
+++
+++  * use dh-acc
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 07 Sep 2015 15:45:20 -0400
+++
+++volk (1.1-1) unstable; urgency=medium
+++
+++  * re-organize package naming convention
+++  * New upstream release tag v1.1
+++  New architectures exist for the AVX2 and FMA ISAs. Along
+++  with the build-system support the following kernels have
+++  no proto-kernels taking advantage of these architectures:
+++
+++  * 32f_x2_dot_prod_32f
+++  * 32fc_x2_multiply_32fc
+++  * 64_byteswap
+++  * 32f_binary_slicer_8i
+++  * 16u_byteswap
+++  * 32u_byteswap
+++
+++  QA/profiler
+++  -----------
+++
+++  The profiler now generates buffers that are vlen + a tiny
+++  amount and generates random data to fill buffers. This is
+++  intended to catch bugs in protokernels that write beyond
+++  num_points.
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 26 Aug 2015 09:22:48 -0400
+++
+++volk (1.0.2-2) unstable; urgency=low
+++
+++  * Use SOURCE_DATE_EPOCH from the environment, if defined,
+++    rather than current date and time to implement volk_build_date()
+++    (embedding build date in a library does not help reproducible builds)
+++  * add watch file
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sat, 15 Aug 2015 17:43:15 -0400
+++
+++volk (1.0.2-1) unstable; urgency=medium
+++
+++  * Maintenance release 24 Jul 2015 by Nathan West
+++  * The major change is the CMake logic to add ASM protokernels. Rather
+++    than depending on CFLAGS and ASMFLAGS we use the results of VOLK's
+++    built in has_ARCH tests. All configurations should work the same as
+++    before, but manually specifying CFLAGS and ASMFLAGS on the cmake call
+++    for ARM native builds should no longer be necessary.
+++  * The 32fc_s32fc_x2_rotator_32fc generic protokernel now includes a
+++    previously implied header.
+++  * Finally, there is a fix to return the "best" protokernel to the
+++    dispatcher when no volk_config exists. Thanks to Alexandre Raymond for
+++    pointing this out.
+++  * with maint branch patch:
+++      kernels-add-missing-include-arm_neon.h
+++  * removed unused build-dependency on liboil0.3-dev (closes: #793626)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 05 Aug 2015 00:43:40 -0400
+++
+++volk (1.0.1-1) unstable; urgency=low
+++
+++  * Maintenance Release v1.0.1 08 Jul 2015 by Nathan West
+++    This is a maintenance release with bug fixes since the initial release of
+++    v1.0 in April.
+++
+++  * Contributors
+++
+++    The following authors have contributed code to this release:
+++
+++    Doug Geiger doug.geiger@bioradiation.net
+++    Elliot Briggs elliot.briggs@gmail.com
+++    Marcus Mueller marcus@hostalia.de
+++    Nathan West nathan.west@okstate.edu
+++    Tom Rondeau tom@trondeau.com
+++
+++  * Kernels
+++
+++    Several bug fixes in different kernels. The NEON implementations of the
+++    following kernels have been fixed:
+++
+++      32f_x2_add_32f
+++      32f_x2_dot_prod_32f
+++      32fc_s32fc_multiply_32fc
+++      32fc_x2_multiply_32fc
+++
+++   Additionally the NEON asm based 32f_x2_add_32f protokernels were not being
+++   used and are now included and available for use via the dispatcher.
+++
+++   The 32f_s32f_x2_fm_detect_32f kernel now has a puppet. This solves QA seg
+++   faults on 32-bit machines and provide a better test for this kernel.
+++
+++   The 32fc_s32fc_x2_rotator_32fc generic protokernel replaced cabsf with
+++   hypotf for better Android support.
+++
+++  * Building
+++
+++    Static builds now trigger the applications (volk_profile and
+++    volk-config-info) to be statically linked.
+++
+++    The file gcc_x86_cpuid.h has been removed since it was no longer being
+++    used. Previously it provided cpuid functionality for ancient compilers
+++    that we do not support.
+++
+++    All build types now use -Wall.
+++
+++  * QA and Testing
+++   
+++   The documentation around the --update option to volk_profile now makes it
+++   clear that the option will only profile kernels without entries in
+++   volk_profile. The signature of run_volk_tests with expanded args changed
+++   signed types to unsigned types to reflect the actual input.
+++   
+++   The remaining changes are all non-functional changes to address issues
+++   from Coverity.
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Fri, 10 Jul 2015 17:57:42 -0400
+++
+++volk (1.0-5) unstable; urgency=medium
+++
+++  * native-armv7-build-support skips neon on Debian armel (Closes: #789972)
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sat, 04 Jul 2015 12:36:36 -0400
+++
+++volk (1.0-4) unstable; urgency=low
+++
+++  * update native-armv7-build-support patch from gnuradio volk package
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 25 Jun 2015 16:38:49 -0400
+++
+++volk (1.0-3) unstable; urgency=medium
+++
+++  * Add Breaks/Replaces (Closes: #789893, #789894)
+++  * Allow failing tests
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Thu, 25 Jun 2015 12:46:06 -0400
+++
+++volk (1.0-2) unstable; urgency=medium
+++
+++  * kernels-add-missing-math.h-include-to-rotator
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Wed, 24 Jun 2015 21:09:32 -0400
+++
+++volk (1.0-1) unstable; urgency=low
+++
+++  * Initial package (Closes: #782417)
+++  Initial Release 11 Apr 2015 by Nathan West
+++
+++  VOLK 1.0 is available. This is the first release of VOLK as an independently
+++  tracked sub-project of GNU Radio.
+++
+++  * Contributors
+++
+++  VOLK has been tracked separately from GNU Radio since 2014 Dec 23.
+++  Contributors between the split and the initial release are
+++
+++  Albert Holguin aholguin_77@yahoo.com
+++  Doug Geiger doug.geiger@bioradiation.net
+++  Elliot Briggs elliot.briggs@gmail.com
+++  Julien Olivain julien.olivain@lsv.ens-cachan.fr
+++  Michael Dickens michael.dickens@ettus.com
+++  Nathan West nathan.west@okstate.edu
+++  Tom Rondeau tom@trondeau.com
+++
+++  * QA
+++
+++  The test and profiler have significantly changed. The profiler supports
+++  run-time changes to vlen and iters to help kernel development and provide
+++  more flexibility on embedded systems. Additionally there is a new option
+++  to update an existing volk_profile results file with only new kernels which
+++  will save time when updating to newer versions of VOLK
+++
+++  The QA system creates a static list of kernels and test cases. The QA
+++  testing and profiler iterate over this static list rather than each source
+++  file keeping its own list. The QA also emits XML results to
+++  lib/.unittest/kernels.xml which is formatted similarly to JUnit results.
+++
+++  * Modtool
+++
+++  Modtool was updated to support the QA and profiler changes.
+++
+++  * Kernels
+++
+++  New proto-kernels:
+++
+++  16ic_deinterleave_real_8i_neon
+++  16ic_s32f_deinterleave_32f_neon
+++  fix preprocessor errors for some compilers on byteswap and popcount puppets
+++
+++  ORC was moved to the asm kernels directory.
+++  volk_malloc
+++
+++  The posix_memalign implementation of Volk_malloc now falls back to a standard
+++  malloc if alignment is 1.
+++
+++  * Miscellaneous
+++
+++  Several build system and cmake changes have made it possible to build VOLK
+++  both independently with proper soname versions and in-tree for projects
+++  such as GNU Radio.
+++
+++  The static builds take advantage of cmake object libraries to speed up builds.
+++
+++  Finally, there are a number of changes to satisfy compiler warnings and make
+++  QA work on multiple machines.
+++
+++ -- A. Maitland Bottoms <bottoms@debian.org>  Sun, 12 Apr 2015 23:20:41 -0400
diff --cc debian/control
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b045f04af2f3f24fe36bdf10dac0f4a17921b01a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,80 @@@@
+++Source: volk
+++Section: libdevel
+++Priority: optional
+++Maintainer: A. Maitland Bottoms <bottoms@debian.org>
+++Build-Depends: cmake,
+++               debhelper-compat (= 13),
+++               dh-python,
+++               liborc-0.4-dev,
+++            python3-dev,
+++            python3-mako
+++Build-Depends-Indep: doxygen, graphviz
+++Standards-Version: 4.5.0
+++Rules-Requires-Root: no
+++Homepage: https://libvolk.org
+++Vcs-Browser: https://salsa.debian.org/bottoms/pkg-volk
+++Vcs-Git: https://salsa.debian.org/bottoms/pkg-volk.git
+++
+++Package: libvolk2.4
+++Section: libs
+++Architecture: any
+++Pre-Depends: ${misc:Pre-Depends}
+++Depends: ${misc:Depends}, ${shlibs:Depends}
+++Multi-Arch: same
+++Recommends: libvolk2-bin
+++Suggests: libvolk2-dev
+++Description: vector optimized functions
+++ Vector-Optimized Library of Kernels is designed to help
+++ applications work with the processor's SIMD instruction sets. These are
+++ very powerful vector operations that can give signal processing a
+++ huge boost in performance.
+++
+++Package: libvolk2-dev
+++Architecture: any
+++Pre-Depends: ${misc:Pre-Depends}
+++Depends: libvolk2.4 (=${binary:Version}), ${misc:Depends}
+++Breaks: gnuradio-dev (<<3.7.8), libvolk-dev, libvolk1.0-dev, libvolk1-dev
+++Replaces: gnuradio-dev (<<3.7.8), libvolk-dev, libvolk1.0-dev, libvolk1-dev
+++Suggests: libvolk2-doc
+++Multi-Arch: same
+++Description: vector optimized function headers
+++ Vector-Optimized Library of Kernels is designed to help
+++ applications work with the processor's SIMD instruction sets. These are
+++ very powerful vector operations that can give signal processing a
+++ huge boost in performance.
+++ .
+++ This package contains the header files.
+++ For documentation, see libvolk-doc.
+++
+++Package: libvolk2-bin
+++Section: libs
+++Architecture: any
+++Pre-Depends: ${misc:Pre-Depends}
+++Depends: libvolk2.4 (=${binary:Version}),
+++         ${misc:Depends},
+++         ${python3:Depends},
+++         ${shlibs:Depends}
+++Breaks: libvolk1-bin, libvolk-bin, libvolk1.0-bin, gnuradio (<=3.7.2.1)
+++Replaces: libvolk1-bin, libvolk-bin, libvolk1.0-bin, gnuradio (<=3.7.2.1)
+++Description: vector optimized runtime tools
+++ Vector-Optimized Library of Kernels is designed to help
+++ applications work with the processor's SIMD instruction sets. These are
+++ very powerful vector operations that can give signal processing a
+++ huge boost in performance.
+++ .
+++ This package includes the volk_profile tool.
+++
+++Package: libvolk2-doc
+++Section: doc
+++Architecture: all
+++Multi-Arch: foreign
+++Depends: ${misc:Depends}
+++Recommends: lynx | www-browser
+++Description: vector optimized library documentation
+++ Vector-Optimized Library of Kernels is designed to help
+++ applications work with the processor's SIMD instruction sets. These are
+++ very powerful vector operations that can give signal processing a
+++ huge boost in performance.
+++ .
+++ This package includes the Doxygen generated documentation in
+++ /usr/share/doc/libvolk2-dev/html/index.html
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..92bbc43812723059171562c28133cdb37eecdb0d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,195 @@@@
+++Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+++Upstream-Name: volk
+++Upstream-Contact: http://libvolk.org/
+++Source:
+++ https://github.com/gnuradio/volk
+++ https://github.com/google/cpu_features
+++Comment:
+++ Debian packages by A. Maitland Bottoms <bottoms@debian.org>
+++ git archive --format=tar --prefix=volk-2.3.0/  v2.3.0  | xz > ../volk_2.3.0.orig.tar.xz
+++ git archive --format=tar --prefix=cpu_features/  v0.6.0  | xz > ../volk_2.4.0.orig-cpu_features.tar.xz
+++ .
+++ Upstream Maintainers:
+++  Johannes Demel <demel@uni-bremen.de>
+++  Michael Dickens <michael.dickens@ettus.com>
+++Copyright: 2014-2020 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: *
+++Copyright: 2006, 2009-2020, Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: Doxyfile.in
+++  DoxygenLayout.xml
+++  volk.pc.in
+++Copyright: 2014-2020 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: apps/volk_profile.h
+++Copyright: 2014-2020 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: appveyor.yml
+++Copyright: 2016 Paul Cercueil <paul.cercueil@analog.com>
+++License: GPL-3+
+++
+++Files: cmake/*
+++Copyright: 2014-2020 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: cmake/Modules/*
+++Copyright: 2006, 2009-2020, Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: cpu_features/*
+++Copyright: 2020 Google LLC
+++License: Apache-2.0
+++ Licensed under the Apache License, Version 2.0 (the "License");
+++ you may not use this file except in compliance with the License.
+++ You may obtain a copy of the License at
+++ .
+++ http://www.apache.org/licenses/LICENSE-2.0
+++ .
+++ Unless required by applicable law or agreed to in writing, software
+++ distributed under the License is distributed on an "AS IS" BASIS,
+++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+++ See the License for the specific language governing permissions and
+++ limitations under the License.
+++ .
+++ On Debian systems, the complete text of the Apache-2.0 License
+++ can be found in "/usr/share/common-licenses/Apache-2.0".
+++
+++Files: cmake/Modules/CMakeParseArgumentsCopy.cmake
+++Copyright: 2010 Alexander Neundorf <neundorf@kde.org>
+++License: Kitware-BSD
+++ All rights reserved.
+++ .
+++ Redistribution and use in source and binary forms, with or without
+++ modification, are permitted provided that the following conditions
+++ are met:
+++ .
+++ * Redistributions of source code must retain the above copyright
+++   notice, this list of conditions and the following disclaimer.
+++ .
+++ * Redistributions in binary form must reproduce the above copyright
+++   notice, this list of conditions and the following disclaimer in the
+++   documentation and/or other materials provided with the distribution.
+++ .
+++ * Neither the names of Kitware, Inc., the Insight Software Consortium,
+++   nor the names of their contributors may be used to endorse or promote
+++   products derived from this software without specific prior written
+++   permission.
+++ .
+++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+++ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+++ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+++ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+++ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+++ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+++ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+++ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+++ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+++
+++Files: cmake/Modules/FindORC.cmake
+++  cmake/Modules/VolkConfig.cmake.in
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: cmake/msvc/*
+++Copyright: 2006-2008, Alexander Chemeris
+++License: BSD-2-clause
+++ Redistribution and use in source and binary forms, with or without
+++ modification, are permitted provided that the following conditions are met:
+++ .
+++   1. Redistributions of source code must retain the above copyright notice,
+++      this list of conditions and the following disclaimer.
+++ .
+++   2. Redistributions in binary form must reproduce the above copyright
+++      notice, this list of conditions and the following disclaimer in the
+++      documentation and/or other materials provided with the distribution.
+++ .
+++   3. The name of the author may be used to endorse or promote products
+++      derived from this software without specific prior written permission.
+++ .
+++ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+++ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+++ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+++ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+++ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+++ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+++ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+++ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+++ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+++
+++Files: debian/*
+++Copyright: 2015-2020 Free Software Foundation, Inc
+++License: GPL-3+
+++Comment: assigned by A. Maitland Bottoms <bottoms@debian.org>
+++
+++Files: docs/*
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: gen/archs.xml
+++  gen/machines.xml
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: include/volk/volk_common.h
+++  include/volk/volk_complex.h
+++  include/volk/volk_prefs.h
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: kernels/volk/asm/*
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: kernels/volk/volk_16u_byteswappuppet_16u.h
+++  kernels/volk/volk_32u_byteswappuppet_32u.h
+++  kernels/volk/volk_64u_byteswappuppet_64u.h
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++Files: lib/kernel_tests.h
+++  lib/qa_utils.cc
+++  lib/qa_utils.h
+++  lib/volk_prefs.c
+++Copyright: 2014-2015 Free Software Foundation, Inc.
+++License: GPL-3+
+++
+++License: LGPL-2+
+++ This library is free software; you can redistribute it and/or
+++ modify it under the terms of the GNU Library General Public
+++ License as published by the Free Software Foundation; either
+++ version 2 of the License, or (at your option) any later version.
+++ .
+++ This library 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
+++ Library General Public License for more details.
+++ .
+++ You should have received a copy of the GNU Library General Public License
+++ along with this library; see the file COPYING.LIB.  If not, write to
+++ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+++ Boston, MA 02110-1301, USA.
+++
+++License: GPL-3+
+++ This program is free software: you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 3 of the License, or
+++ (at your option) any later version.
+++ .
+++ This program 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 General Public License for more details.
+++ .
+++ You should have received a copy of the GNU General Public License
+++ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+++ .
+++ On Debian systems, the complete text of the GNU General
+++ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7221b71b302ef2f0ded6afe2d91854021b9dd39e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,2 @@@@
+++usr/bin/volk*
+++usr/lib/python3/dist-packages
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..95bae9ed64bf63074c84a8443157200593ecd7b9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,3 @@@@
+++debian/volk-config-info.1
+++debian/volk_modtool.1
+++debian/volk_profile.1
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..37f5a797b2f333aab8d37480c3472dcf12c90b7b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,50 @@@@
+++<?xml version="1.0" encoding="utf-8"?>
+++<descriptor>
+++
+++  <gcc_options>
+++    -DHAVE_CPUID_H
+++    -DHAVE_DLFCN_H
+++    -DHAVE_FENV_H
+++    -DHAVE_POSIX_MEMALIGN
+++    -DHAVE_XGETBV
+++    -D_GLIBCXX_USE_CXX11_ABI=1
+++    -I/usr/include/orc-0.4
+++    -DNDEBUG
+++    -std=gnu11
+++    -m64
+++    -mmmx
+++    -msse
+++    -msse2
+++    -msse3
+++    -mssse3
+++    -msse4.1
+++    -msse4.2
+++    -mpopcnt
+++    -mavx
+++    -mfma
+++    -mavx2
+++    -mavx512f
+++    -mavx512cd
+++    -fPIC
+++    -g
+++    -O2
+++    -fstack-protector-strong
+++    -Wformat
+++    -Werror=format-security
+++    -Wdate-time
+++    -D_FORTIFY_SOURCE=2
+++    -fvisibility=hidden
+++    -Wsign-compare
+++    -Wall
+++    -Wno-uninitialized
+++</gcc_options>
+++
+++<headers>
+++debian/libvolk2-dev/usr/include/volk/
+++</headers>
+++
+++<libs>
+++debian/libvolk2.0/usr/lib/
+++</libs>
+++
+++</descriptor>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8b14c562bc6f1906b805c0c492cf1ee3d284fcb1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,5 @@@@
+++usr/include/*
+++usr/lib/*/*volk.a
+++usr/lib/*/*volk*so
+++usr/lib/*/cmake/volk
+++usr/lib/*/pkgconfig/*volk*
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3d5fdc804a6161dea2eae94d0042a7734a1cf60f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,19 @@@@
+++Document: libvolk2-doc
+++Title: Vector-Optimized Library of Kernels Reference Manual
+++Author: GNU Radio Developers
+++Abstract: VOLK is the Vector-Optimized Library of Kernels.
+++ It is a library that contains kernels of hand-written SIMD code for
+++ different mathematical operations. Since each SIMD architecture can
+++ be very different and no compiler has yet come along to handle
+++ vectorization properly or highly efficiently, VOLK approaches the
+++ problem differently. For each architecture or platform that a
+++ developer wishes to vectorize for, a new proto-kernel is added to
+++ VOLK. At runtime, VOLK will select the correct proto-kernel. In this
+++ way, the users of VOLK call a kernel for performing the operation
+++ that is platform/architecture agnostic. This allows us to write
+++ portable SIMD code.
+++Section: Programming/C++
+++
+++Format: HTML
+++Index: /usr/share/doc/libvolk2-dev/html/index.html
+++Files: /usr/share/doc/libvolk2-dev/html/*.html
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..87dd3148770f0c11566575da299d83a2108ae45f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,1 @@@@
+++obj-*/html
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e4252f46b63bd3c4b8896a2294216d7023ea526b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,1 @@@@
+++usr/lib/*/libvolk.so.*
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6f354d05baed1d29759dd695194ca31a8ec6418d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,6 @@@@
+++usr/bin/list_cpu_features
+++usr/lib/*/cmake/CpuFeatures/CpuFeaturesConfig.cmake
+++usr/lib/*/cmake/CpuFeatures/CpuFeaturesConfigVersion.cmake
+++usr/lib/*/cmake/CpuFeatures/CpuFeaturesTargets-relwithdebinfo.cmake
+++usr/lib/*/cmake/CpuFeatures/CpuFeaturesTargets.cmake
+++usr/lib/*/libcpu_features.a
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e30d9307de75a21776070814c880dfe9e8ef5725
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,105 @@@@
+++From 21201840dc294affbfc173868bc55569ef114655 Mon Sep 17 00:00:00 2001
+++From: "A. Maitland Bottoms" <bottoms@debian.org>
+++Date: Tue, 1 Dec 2020 11:29:12 -0500
+++Subject: [PATCH] cpu_features CMake option
+++
+++Make use of cpu_features a CMake option with sensible defaults per arch.
+++(avoiding CMake failures of cpu_features for unknown architectures)
+++---
+++ CMakeLists.txt       | 23 +++++++++++++++++------
+++ lib/CMakeLists.txt   | 12 ++++++++++--
+++ tmpl/volk_cpu.tmpl.c |  2 ++
+++ 3 files changed, 29 insertions(+), 8 deletions(-)
+++
+++diff --git a/CMakeLists.txt b/CMakeLists.txt
+++index eb73e20..f905230 100644
+++--- a/CMakeLists.txt
++++++ b/CMakeLists.txt
+++@@ -114,14 +114,25 @@ endif(MSVC)
+++ # Dependencies setup
+++ ########################################################################
+++ 
+++-# cpu_features
+++-set(BUILD_PIC ON CACHE BOOL
++++# cpu_features - sensible defaults, user settable option
++++if(CMAKE_SYSTEM_PROCESSOR MATCHES
++++    "(^mips)|(^arm)|(^aarch64)|(x86_64)|(AMD64|amd64)|(^i.86$)|(^powerpc)|(^ppc)")
++++  option(VOLK_CPU_FEATURES "Volk uses cpu_features" ON)
++++else()
++++  option(VOLK_CPU_FEATURES "Volk uses cpu_features" OFF)
++++endif()
++++if (VOLK_CPU_FEATURES)
++++  message(STATUS "Building Volk with cpu_features")
++++  set(BUILD_PIC ON CACHE BOOL
+++     "Build cpu_features with Position Independent Code (PIC)."
+++     FORCE)
+++-set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
+++-set(BUILD_SHARED_LIBS OFF)
+++-add_subdirectory(cpu_features)
+++-set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
++++  set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
++++  set(BUILD_SHARED_LIBS OFF)
++++  add_subdirectory(cpu_features)
++++  set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
++++else()
++++  message(STATUS "Building Volk without cpu_features")
++++endif()
+++ 
+++ # Python
+++ include(VolkPython) #sets PYTHON_EXECUTABLE and PYTHON_DASH_B
+++diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
+++index 7458530..9fbdb92 100644
+++--- a/lib/CMakeLists.txt
++++++ b/lib/CMakeLists.txt
+++@@ -511,10 +511,15 @@ target_include_directories(volk_obj
+++     PRIVATE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+++     PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+++     PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/kernels>
+++-    PRIVATE $<TARGET_PROPERTY:cpu_features,INTERFACE_INCLUDE_DIRECTORIES>
+++     PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
+++     PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+++ )
++++if(VOLK_CPU_FEATURES)
++++  set_source_files_properties(volk_cpu.c PROPERTIES COMPILE_DEFINITIONS "VOLK_CPU_FEATURES=1")
++++  target_include_directories(volk_obj
++++    PRIVATE $<TARGET_PROPERTY:cpu_features,INTERFACE_INCLUDE_DIRECTORIES>
++++)
++++endif()
+++ 
+++ #Configure object target properties
+++ if(NOT MSVC)
+++@@ -530,7 +535,10 @@ endif()
+++ #include directories is taken as provided; it -might- matter, but
+++ #probably doesn't.
+++ add_library(volk SHARED $<TARGET_OBJECTS:volk_obj>)
+++-target_link_libraries(volk PUBLIC ${volk_libraries} PRIVATE cpu_features)
++++target_link_libraries(volk PUBLIC ${volk_libraries})
++++if(VOLK_CPU_FEATURES)
++++  target_link_libraries(volk PRIVATE cpu_features)
++++endif()
+++ target_include_directories(volk
+++     PUBLIC $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+++     PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+++diff --git a/tmpl/volk_cpu.tmpl.c b/tmpl/volk_cpu.tmpl.c
+++index 1266250..f879eb6 100644
+++--- a/tmpl/volk_cpu.tmpl.c
++++++ b/tmpl/volk_cpu.tmpl.c
+++@@ -25,6 +25,7 @@
+++ #include <string.h>
+++ 
+++ 
++++#if defined(VOLK_CPU_FEATURES)
+++ #include "cpu_features_macros.h"
+++ #if defined(CPU_FEATURES_ARCH_X86)
+++ #include "cpuinfo_x86.h"
+++@@ -42,6 +43,7 @@
+++ #if defined(__cplusplus)
+++ using namespace cpu_features;
+++ #endif
++++#endif
+++ 
+++ 
+++ struct VOLK_CPU volk_cpu;
+++-- 
+++2.20.1
+++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7c5c76774571e3c12310bb8b7d6949aad953867d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,60 @@@@
+++From 799245ea6e9e05cc0ed0fabe783fbbe1a5054fd4 Mon Sep 17 00:00:00 2001
+++From: "A. Maitland Bottoms" <bottoms@debian.org>
+++Date: Tue, 27 Mar 2018 22:02:59 -0400
+++Subject: [PATCH 2/6] make acc happy
+++
+++The abi-compliance-checker grabs all the .h files it finds
+++and tries to compile them all. Even though some are not
+++appropriate for the architecture being run on. Being careful
+++with preprocessor protections avoids problems.
+++---
+++ include/volk/volk_neon_intrinsics.h                 | 2 ++
+++ kernels/volk/volk_32f_8u_polarbutterflypuppet_32f.h | 1 +
+++ kernels/volk/volk_8u_x2_encodeframepolar_8u.h       | 3 ---
+++ 3 files changed, 3 insertions(+), 3 deletions(-)
+++
+++--- a/include/volk/volk_neon_intrinsics.h
++++++ b/include/volk/volk_neon_intrinsics.h
+++@@ -79,6 +79,7 @@
+++ 
+++ #ifndef INCLUDE_VOLK_VOLK_NEON_INTRINSICS_H_
+++ #define INCLUDE_VOLK_VOLK_NEON_INTRINSICS_H_
++++#ifdef LV_HAVE_NEON
+++ #include <arm_neon.h>
+++ 
+++ 
+++@@ -278,4 +279,5 @@
+++ }
+++ 
+++ 
++++#endif /*LV_HAVE_NEON*/
+++ #endif /* INCLUDE_VOLK_VOLK_NEON_INTRINSICS_H_ */
+++--- a/kernels/volk/volk_32f_8u_polarbutterflypuppet_32f.h
++++++ b/kernels/volk/volk_32f_8u_polarbutterflypuppet_32f.h
+++@@ -31,6 +31,7 @@
+++ #include <volk/volk_32f_8u_polarbutterfly_32f.h>
+++ #include <volk/volk_8u_x3_encodepolar_8u_x2.h>
+++ #include <volk/volk_8u_x3_encodepolarpuppet_8u.h>
++++#include <volk/volk_8u_x2_encodeframepolar_8u.h>
+++ 
+++ 
+++ static inline void sanitize_bytes(unsigned char* u, const int elements)
+++--- a/kernels/volk/volk_8u_x2_encodeframepolar_8u.h
++++++ b/kernels/volk/volk_8u_x2_encodeframepolar_8u.h
+++@@ -60,8 +60,6 @@
+++     }
+++ }
+++ 
+++-#ifdef LV_HAVE_GENERIC
+++-
+++ static inline void volk_8u_x2_encodeframepolar_8u_generic(unsigned char* frame,
+++                                                           unsigned char* temp,
+++                                                           unsigned int frame_size)
+++@@ -81,7 +79,6 @@
+++         --stage;
+++     }
+++ }
+++-#endif /* LV_HAVE_GENERIC */
+++ 
+++ #ifdef LV_HAVE_SSSE3
+++ #include <tmmintrin.h>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..399ee9b0936f62c975e8ca35e561add76434152a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,20 @@@@
+++--- a/apps/CMakeLists.txt
++++++ b/apps/CMakeLists.txt
+++@@ -62,7 +62,7 @@
+++     target_link_libraries(volk_profile PRIVATE std::filesystem)
+++ endif()
+++ 
+++-if(ENABLE_STATIC_LIBS)
++++if(ENABLE_STATIC_LIBS AND ENABLE_STATIC_APPS)
+++     target_link_libraries(volk_profile PRIVATE volk_static)
+++     set_target_properties(volk_profile PROPERTIES LINK_FLAGS "-static")
+++ else()
+++@@ -79,7 +79,7 @@
+++ add_executable(volk-config-info volk-config-info.cc ${CMAKE_CURRENT_SOURCE_DIR}/volk_option_helpers.cc
+++         )
+++ 
+++-if(ENABLE_STATIC_LIBS)
++++if(ENABLE_STATIC_LIBS AND ENABLE_STATIC_APPS)
+++     target_link_libraries(volk-config-info volk_static)
+++     set_target_properties(volk-config-info PROPERTIES LINK_FLAGS "-static")
+++ else()
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..924c1ad4a15c03613d4d00418e6ceb52fb77b1cc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,18 @@@@
+++--- a/README.md
++++++ b/README.md
+++@@ -1,7 +1,3 @@
+++-[![Build Status](https://travis-ci.org/gnuradio/volk.svg?branch=master)](https://travis-ci.org/gnuradio/volk) [![Build status](https://ci.appveyor.com/api/projects/status/5o56mgw0do20jlh3/branch/master?svg=true)](https://ci.appveyor.com/project/gnuradio/volk/branch/master)
+++-![Check PR Formatting](https://github.com/gnuradio/volk/workflows/Check%20PR%20Formatting/badge.svg)
+++-![Run VOLK tests](https://github.com/gnuradio/volk/workflows/Run%20VOLK%20tests/badge.svg)
+++-
+++ ![VOLK Logo](/docs/volk_logo.png)
+++ 
+++ # Welcome to VOLK!
+++--- a/cpu-features/README.md
++++++ b/cpu-features/README.md
+++@@ -1,4 +1,4 @@
+++-# cpu_features [![Build Status](https://travis-ci.org/google/cpu_features.svg?branch=master)](https://travis-ci.org/google/cpu_features) [![Build status](https://ci.appveyor.com/api/projects/status/46d1owsj7n8dsylq/branch/master?svg=true)](https://ci.appveyor.com/project/gchatelet/cpu-features/branch/master)
++++# cpu_features
+++ 
+++ A cross-platform C library to retrieve CPU features (such as available
+++ instructions) at runtime.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f84bed1ae49496d63f6000db19ff86230deceaa6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,4 @@@@
+++make-acc-happy
+++optional-static-apps
+++remove-external-HTML-resources
+++cpu_features-CMake-option
diff --cc debian/rules
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..94eca1da0767ae1a430e9267a98113a94da4a691
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,20 @@@@
+++#!/usr/bin/make -f
+++DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+++export DEB_HOST_MULTIARCH
+++#export DH_VERBOSE=1
+++
+++%:
+++     dh $@ --with python3
+++
+++override_dh_auto_configure:
+++     - mv cpu-features/* cpu_features/
+++     dh_auto_configure -- -DLIB_SUFFIX="/$(DEB_HOST_MULTIARCH)" \
+++     -DENABLE_STATIC_LIBS=On -DPYTHON_EXECUTABLE=/usr/bin/python3 \
+++     -DCMAKE_BUILD_TYPE=RelWithDebInfo
+++
+++override_dh_auto_build-indep:
+++     cmake --build obj-* --target all
+++     cmake --build obj-* --target volk_doc
+++
+++override_dh_auto_test:
+++     - dh_auto_test -- CTEST_TEST_TIMEOUT=60
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..163aaf8d82b6c54f23c45f32895dbdfdcc27b047
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,1 @@@@
+++3.0 (quilt)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e8d6efdbbcbde3a07e31471d786985614a36aaad
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,45 @@@@
+++.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.40.10.
+++.TH VOLK-CONFIG-INFO "1" "July 2014" "volk-config-info 0.1" "User Commands"
+++.SH NAME
+++volk-config-info \- pkgconfig-like tool for Vector Optimized Library of Kernels 0.1
+++.SH DESCRIPTION
+++.SS "Program options: volk-config-info [options]:"
+++.TP
+++\fB\-h\fR [ \fB\-\-help\fR ]
+++print help message
+++.TP
+++\fB\-\-prefix\fR
+++print VOLK installation prefix
+++.TP
+++\fB\-\-builddate\fR
+++print VOLK build date (RFC2822 format)
+++.TP
+++\fB\-\-cc\fR
+++print VOLK C compiler version
+++.TP
+++\fB\-\-cflags\fR
+++print VOLK CFLAGS
+++.TP
+++\fB\-\-all\-machines\fR
+++print VOLK machines built into library
+++.TP
+++\fB\-\-avail\-machines\fR
+++print VOLK machines the current platform can use
+++.TP
+++\fB\-\-machine\fR
+++print the VOLK machine that will be used
+++.TP
+++\fB\-v\fR [ \fB\-\-version\fR ]
+++print VOLK version
+++.SH "SEE ALSO"
+++The full documentation for
+++.B volk-config-info
+++is maintained as a Texinfo manual.  If the
+++.B info
+++and
+++.B volk-config-info
+++programs are properly installed at your site, the command
+++.IP
+++.B info volk-config-info
+++.PP
+++should give you access to the complete manual.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..752e7f53d2d30c2dccf506e7423df16eac02a1c8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,112 @@@@
+++.TH GNURADIO "1" "August 2013" "volk_modtool 3.7" "User Commands"
+++.SH NAME
+++volk_modtool \- tailor VOLK modules
+++.SH DESCRIPTION
+++The volk_modtool tool is installed along with VOLK as a way of helping
+++to construct, add to, and interogate the VOLK library or companion
+++libraries.
+++.P
+++volk_modtool is installed into $prefix/bin.
+++.P
+++VOLK modtool enables creating standalone (out-of-tree) VOLK modules
+++and provides a few tools for sharing VOLK kernels between VOLK
+++modules.  If you need to design or work with VOLK kernels away from
+++the canonical VOLK library, this is the tool.  If you need to tailor
+++your own VOLK library for whatever reason, this is the tool.
+++.P
+++The canonical VOLK library installs a volk.h and a libvolk.so.  Your
+++own library will install volk_$name.h and libvolk_$name.so.  Ya Gronk?
+++Good.
+++.P
+++There isn't a substantial difference between the canonical VOLK
+++module and any other VOLK module.  They're all peers.  Any module
+++created via VOLK modtool will come complete with a default
+++volk_modtool.cfg file associating the module with the base from which
+++it came, its distinctive $name and its destination (or path).  These
+++values (created from user input if VOLK modtool runs without a
+++user-supplied config file or a default config file) serve as default
+++values for some VOLK modtool actions.  It's more or less intended for
+++the user to change directories to the top level of a created VOLK
+++module and then run volk_modtool to take advantage of the values
+++stored in the default volk_modtool.cfg file.
+++.P
+++Apart from creating new VOLK modules, VOLK modtool allows you to list
+++the names of kernels in other modules, list the names of kernels in
+++the current module, add kernels from another module into the current
+++module, and remove kernels from the current module.  When moving
+++kernels between modules, VOLK modtool does its best to keep the qa
+++and profiling code for those kernels intact.  If the base has a test
+++or a profiling call for some kernel, those calls will follow the
+++kernel when VOLK modtool adds that kernel.  If QA or profiling
+++requires a puppet kernel, the puppet kernel will follow the original
+++kernel when VOLK modtool adds that original kernel.  VOLK modtool
+++respects puppets.
+++.P
+++======================================================================
+++.P
+++.SH Installing a new VOLK Library:
+++.P
+++Run the command "volk_modtool -i". This will ask you three questions:
+++.P
+++  name: // the name to give your VOLK library: volk_<name>
+++  destination: // directory new source tree is built under -- must exists.
+++               // It will create <directory>/volk_<name>
+++  base: // the directory containing the original VOLK source code
+++.P
+++This will build a new skeleton directory in the destination provided
+++with the name volk_<name>. It will contain the necessary structure to
+++build:
+++.P
+++  mkdir build
+++  cd build
+++  cmake -DCMAKE_INSTALL_PREFIX=/opt/volk ../
+++  make
+++  sudo make install
+++.P
+++Right now, the library is empty and contains no kernels. Kernels can
+++be added from another VOLK library using the '-a' option. If not
+++specified, the kernel will be extracted from the base VOLK
+++directory. Using the '-b' allows us to specify another VOLK library to
+++use for this purpose.
+++.P
+++  volk_modtool -a -n 32fc_x2_conjugate_dot_prod_32fc
+++.P
+++This will put the code for the new kernel into
+++<destination>/volk_<name>/kernels/volk_<name>/
+++.P
+++Other kernels must be added by hand. See the following webpages for
+++more information about creating VOLK kernels:
+++  http://gnuradio.org/doc/doxygen/volk_guide.html
+++  http://gnuradio.org/redmine/projects/gnuradio/wiki/Volk
+++.P
+++======================================================================
+++.P
+++.SH OPTIONS
+++.P
+++Options for Adding and Removing Kernels:
+++  -a, --add_kernel
+++       Add kernel from existing VOLK module. Uses the base VOLK module
+++       unless -b is used. Use -n to specify the kernel name.
+++       Requires: -n.
+++       Optional: -b
+++.P
+++  -A, --add_all_kernels
+++       Add all kernels from existing VOLK module. Uses the base VOLK
+++       module unless -b is used.
+++       Optional: -b
+++.P
+++  -x, --remove_kernel
+++       Remove kernel from module. 
+++       Required: -n.
+++       Optional: -b
+++.P
+++Options for Listing Kernels:
+++  -l, --list
+++       Lists all kernels available in the base VOLK module.
+++.P
+++  -k, --kernels 
+++       Lists all kernels in this VOLK module.
+++.P
+++  -r, --remote-list
+++       Lists all kernels in another VOLK module that is specified
+++       using the -b option.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..405facbf04075e7ec73f9429398e46a5a51857c7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,5 @@@@
+++.TH UHD_FFT "1" "March 2012" "volk_profile 3.5" "User Commands"
+++.SH NAME
+++volk_profile \- Quality Assurance application for libvolk functions
+++.SH DESCRIPTION
+++Writes profile results to a file.
diff --cc debian/watch
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..de9e7d17bdf68360319c551df5aa76b8b8c0b317
new file mode 100644 (file)
--- /dev/null
--- /dev/null
--- /dev/null
@@@@ -1,0 -1,0 -1,0 +1,4 @@@@
+++version=4
+++ opts="filenamemangle=s%(?:.*?)?volk-?(\d[\d.]*)\.tar\.xz%volk_$1.orig.tar.xz%" \
+++ https://github.com/gnuradio/volk/releases \
+++ (?:.*?/)?volk-?(\d[\d.]*)\.tar\.xz debian uupdate