aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-09-23 03:05:30 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-09-23 03:05:30 +0000
commit694e39495b2732503c40303662d9e27a1dbb491a (patch)
tree6024c46d82d3a8d8bd952ffdca5f23cb37d9072d
parent0b9bc62e34848ee8455f10e7f7a5970d91835584 (diff)
parenteca53ba6d2e951e174b64682eaf56a36b8204c89 (diff)
downloadcpu_features-android14-qpr2-s1-release.tar.gz
Change-Id: I7dfbdbfd57e17d3714c2e93cb632f9811eaf0463
-rw-r--r--.dockerignore13
-rw-r--r--.github/workflows/Dockerfile1
-rw-r--r--.github/workflows/aarch64_linux_bazel.yml26
-rw-r--r--.github/workflows/amd64_freebsd_cmake.yml2
-rw-r--r--.github/workflows/amd64_linux_bazel.yml18
-rw-r--r--.github/workflows/amd64_macos_bazel.yml35
-rw-r--r--.github/workflows/clang_format.yml2
-rw-r--r--BUILD.bazel65
-rw-r--r--CMakeLists.txt127
-rw-r--r--METADATA6
-rw-r--r--README.md68
-rw-r--r--bazel/ci/Makefile122
-rw-r--r--bazel/ci/docker/Dockerfile37
-rw-r--r--bazel/platforms.bzl7
-rw-r--r--cmake/README.md2
-rw-r--r--include/cpu_features_macros.h4
-rw-r--r--include/cpuinfo_aarch64.h42
-rw-r--r--include/cpuinfo_loongarch.h77
-rw-r--r--include/cpuinfo_x86.h7
-rw-r--r--include/internal/hwcaps.h37
-rwxr-xr-x[-rw-r--r--]scripts/generate_badges.d107
-rw-r--r--src/impl_aarch64__base_implementation.inl118
-rw-r--r--src/impl_aarch64_linux_or_android.c76
-rw-r--r--src/impl_aarch64_macos_or_iphone.c88
-rw-r--r--src/impl_loongarch_linux.c89
-rw-r--r--src/impl_x86__base_implementation.inl16
-rw-r--r--src/utils/list_cpu_features.c9
-rw-r--r--test/CMakeLists.txt19
-rw-r--r--test/cpuinfo_aarch64_test.cc146
-rw-r--r--test/cpuinfo_loongarch_test.cc179
-rw-r--r--test/cpuinfo_x86_test.cc61
31 files changed, 1366 insertions, 240 deletions
diff --git a/.dockerignore b/.dockerignore
index 65950ea..5169bae 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,8 +1,4 @@
# Project Files unneeded by docker
-cmake/ci/Makefile
-cmake/ci/docker
-cmake/ci/doc
-cmake/ci/cache
.git
.gitignore
.github
@@ -16,6 +12,15 @@ CONTRIBUTORS
LICENSE
README.md
+bazel/ci/Makefile
+bazel/ci/docker
+bazel/ci/doc
+
+cmake/ci/Makefile
+cmake/ci/docker
+cmake/ci/doc
+cmake/ci/cache
+
build/
cmake_build/
build_cross/
diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile
index 8d6f3dc..28371cb 100644
--- a/.github/workflows/Dockerfile
+++ b/.github/workflows/Dockerfile
@@ -3,3 +3,4 @@
FROM alpine:edge
# Install system build dependencies
RUN apk add --no-cache git clang-extra-tools
+RUN git config --global --add safe.directory /repo
diff --git a/.github/workflows/aarch64_linux_bazel.yml b/.github/workflows/aarch64_linux_bazel.yml
new file mode 100644
index 0000000..72dbfff
--- /dev/null
+++ b/.github/workflows/aarch64_linux_bazel.yml
@@ -0,0 +1,26 @@
+name: AArch64 Linux Bazel
+
+on:
+ push:
+ pull_request:
+ schedule:
+ # min hours day(month) month day(week)
+ - cron: '0 0 7,22 * *'
+
+jobs:
+ # Building using the github runner environement directly.
+ bazel:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v3
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+ - name: Check docker
+ run: |
+ docker info
+ docker buildx ls
+ - name: Build
+ run: make --directory=bazel/ci arm64_build
+ - name: Test
+ run: make --directory=bazel/ci arm64_test
diff --git a/.github/workflows/amd64_freebsd_cmake.yml b/.github/workflows/amd64_freebsd_cmake.yml
index 8bad4f8..37c95d7 100644
--- a/.github/workflows/amd64_freebsd_cmake.yml
+++ b/.github/workflows/amd64_freebsd_cmake.yml
@@ -11,7 +11,7 @@ jobs:
# Only MacOS hosted runner provides virtualisation with vagrant/virtualbox installed.
# see: https://github.com/actions/virtual-environments/tree/main/images/macos
make:
- runs-on: macos-10.15
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: vagrant version
diff --git a/.github/workflows/amd64_linux_bazel.yml b/.github/workflows/amd64_linux_bazel.yml
index 599faf5..fcb0ce4 100644
--- a/.github/workflows/amd64_linux_bazel.yml
+++ b/.github/workflows/amd64_linux_bazel.yml
@@ -13,14 +13,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
- uses: actions/checkout@v2
- - name: Install Bazel
+ uses: actions/checkout@v3
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+ - name: Check docker
run: |
- curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
- sudo mv bazel.gpg /etc/apt/trusted.gpg.d/
- echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
- sudo apt-get update
- sudo apt-get install bazel
- bazel --version
+ docker info
+ docker buildx ls
+ - name: Build
+ run: make --directory=bazel/ci amd64_build
- name: Test
- run: bazel test -s --verbose_failures //...
+ run: make --directory=bazel/ci amd64_test
diff --git a/.github/workflows/amd64_macos_bazel.yml b/.github/workflows/amd64_macos_bazel.yml
new file mode 100644
index 0000000..fd1bc5a
--- /dev/null
+++ b/.github/workflows/amd64_macos_bazel.yml
@@ -0,0 +1,35 @@
+name: amd64 MacOS Bazel
+
+on:
+ push:
+ pull_request:
+ schedule:
+ # min hours day(month) month day(week)
+ - cron: '0 0 7,22 * *'
+
+jobs:
+ # Building using the github runner environement directly.
+ bazel:
+ runs-on: macos-latest
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v3
+ - name: Install Bazel
+ run: |
+ brew update
+ brew unlink bazelisk
+ brew install bazel
+ - name: Check Bazel
+ run: bazel version
+ - name: Build
+ run: >
+ bazel build
+ -c opt
+ --subcommands=true
+ ...
+ - name: Test
+ run: >
+ bazel test
+ -c opt
+ --test_output=errors
+ ...
diff --git a/.github/workflows/clang_format.yml b/.github/workflows/clang_format.yml
index 1afd391..2ab0de0 100644
--- a/.github/workflows/clang_format.yml
+++ b/.github/workflows/clang_format.yml
@@ -7,7 +7,7 @@ jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Fetch origin/main
run: git fetch origin main
- name: List of changed file(s)
diff --git a/BUILD.bazel b/BUILD.bazel
index 116ef6a..6925944 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,7 +1,8 @@
# cpu_features, a cross platform C99 library to get cpu features at runtime.
load("@bazel_skylib//lib:selects.bzl", "selects")
-load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_X86_64")
+load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_RISCV32", "PLATFORM_CPU_RISCV64", "PLATFORM_CPU_X86_64")
+load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS")
package(
default_visibility = ["//visibility:public"],
@@ -170,7 +171,10 @@ cc_library(
name = "hwcaps",
srcs = ["src/hwcaps.c"],
copts = C99_FLAGS,
- defines = ["HAVE_STRONG_GETAUXVAL"],
+ defines = selects.with_or({
+ PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"],
+ "//conditions:default": ["HAVE_STRONG_GETAUXVAL"],
+ }),
includes = INCLUDES,
textual_hdrs = ["include/internal/hwcaps.h"],
deps = [
@@ -213,15 +217,18 @@ cc_library(
"src/impl_x86_windows.c",
],
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
- PLATFORM_CPU_ARM64: ["src/impl_aarch64_linux_or_android.c"],
+ PLATFORM_CPU_ARM64: [
+ "src/impl_aarch64_linux_or_android.c",
+ "src/impl_aarch64_macos_or_iphone.c",
+ "src/impl_aarch64_windows.c",
+ ],
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
+ PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"],
+ PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"],
}),
- copts = C99_FLAGS,
- includes = INCLUDES,
- textual_hdrs = selects.with_or({
+ hdrs = selects.with_or({
PLATFORM_CPU_X86_64: [
- "src/impl_x86__base_implementation.inl",
"include/cpuinfo_x86.h",
"include/internal/cpuid_x86.h",
"include/internal/windows_utils.h",
@@ -230,6 +237,19 @@ cc_library(
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
+ PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
+ PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"],
+ }),
+ copts = C99_FLAGS,
+ defines = selects.with_or({
+ PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"],
+ "//conditions:default": [],
+ }),
+ includes = INCLUDES,
+ textual_hdrs = selects.with_or({
+ PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
+ PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"],
+ "//conditions:default": [],
}) + [
"src/define_introspection.inl",
"src/define_introspection_and_hwcaps.inl",
@@ -257,9 +277,15 @@ cc_library(
"src/impl_x86_windows.c",
],
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
- PLATFORM_CPU_ARM64: ["src/impl_aarch64_linux_or_android.c"],
+ PLATFORM_CPU_ARM64: [
+ "src/impl_aarch64_linux_or_android.c",
+ "src/impl_aarch64_macos_or_iphone.c",
+ "src/impl_aarch64_windows.c",
+ ],
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
+ PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"],
+ PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"],
}),
hdrs = selects.with_or({
PLATFORM_CPU_X86_64: [
@@ -271,15 +297,21 @@ cc_library(
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
+ PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
+ PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"],
}),
copts = C99_FLAGS,
defines = selects.with_or({
PLATFORM_CPU_X86_64: ["CPU_FEATURES_MOCK_CPUID_X86"],
"//conditions:default": [],
+ }) + selects.with_or({
+ PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"],
+ "//conditions:default": [],
}),
includes = INCLUDES,
textual_hdrs = selects.with_or({
PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
+ PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"],
"//conditions:default": [],
}) + [
"src/define_introspection.inl",
@@ -304,6 +336,8 @@ cc_test(
PLATFORM_CPU_ARM: ["test/cpuinfo_arm_test.cc"],
PLATFORM_CPU_MIPS: ["test/cpuinfo_mips_test.cc"],
PLATFORM_CPU_PPC: ["test/cpuinfo_ppc_test.cc"],
+ PLATFORM_CPU_RISCV32: ["test/cpuinfo_riscv_test.cc"],
+ PLATFORM_CPU_RISCV64: ["test/cpuinfo_riscv_test.cc"],
PLATFORM_CPU_X86_64: ["test/cpuinfo_x86_test.cc"],
}),
includes = INCLUDES,
@@ -327,3 +361,18 @@ cc_binary(
":cpuinfo",
],
)
+
+cc_library(
+ name = "ndk_compat",
+ srcs = ["ndk_compat/cpu-features.c"],
+ copts = C99_FLAGS,
+ includes = INCLUDES + ["ndk_compat"],
+ textual_hdrs = ["ndk_compat/cpu-features.h"],
+ deps = [
+ ":cpu_features_macros",
+ ":cpuinfo",
+ ":filesystem",
+ ":stack_line_reader",
+ ":string_view",
+ ],
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bcc9bb0..0454967 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.13)
# option() honors normal variables.
# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
@@ -6,10 +6,18 @@ if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
-project(CpuFeatures VERSION 0.8.0 LANGUAGES C)
+project(CpuFeatures VERSION 0.9.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
+# when cpu_features is included as subproject (i.e. using add_subdirectory(cpu_features))
+# in the source tree of a project that uses it, test rules are disabled.
+if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ option(BUILD_TESTING "Enable test rule" OFF)
+else()
+ option(BUILD_TESTING "Enable test rule" ON)
+endif()
+
# Default Build Type to be Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
@@ -17,6 +25,22 @@ if(NOT CMAKE_BUILD_TYPE)
FORCE)
endif(NOT CMAKE_BUILD_TYPE)
+# An option to enable/disable the executable target list_cpu_features.
+# Disable it by default if the project is included as a subproject.
+if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ option(BUILD_EXECUTABLE "Build list_cpu_features executable." OFF)
+else()
+ option(BUILD_EXECUTABLE "Build list_cpu_features executable." ON)
+endif()
+
+# An option which allows to switch off install steps. Useful for embedding.
+# Disable it by default if the project is included as a subproject.
+if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ option(ENABLE_INSTALL "Enable install targets" OFF)
+else()
+ option(ENABLE_INSTALL "Enable install targets" ON)
+endif()
+
# 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).
@@ -51,14 +75,15 @@ set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
set(PROCESSOR_IS_S390X FALSE)
set(PROCESSOR_IS_RISCV FALSE)
+set(PROCESSOR_IS_LOONGARCH FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)")
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(^arm64)|(^ARM64)")
set(PROCESSOR_IS_AARCH64 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(PROCESSOR_IS_ARM TRUE)
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(x86_64)|(AMD64|amd64)|(^i.86$)")
set(PROCESSOR_IS_X86 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
@@ -66,6 +91,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
set(PROCESSOR_IS_S390X TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
set(PROCESSOR_IS_RISCV TRUE)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^loongarch")
+ set(PROCESSOR_IS_LOONGARCH TRUE)
endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
@@ -90,6 +117,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
elseif(PROCESSOR_IS_RISCV)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h)
+ elseif(PROCESSOR_IS_LOONGARCH)
+ list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_loongarch.h)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
@@ -147,20 +176,21 @@ target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
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()
+
+if(APPLE)
+ target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
endif()
-add_library(CpuFeature::cpu_features ALIAS cpu_features)
+add_library(CpuFeatures::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)
+if(BUILD_EXECUTABLE)
+ 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(CpuFeatures::list_cpu_features ALIAS list_cpu_features)
+endif()
#
# ndk_compat
@@ -226,36 +256,47 @@ 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}
- BUNDLE 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
+if(ENABLE_INSTALL)
+ include(GNUInstallDirs)
+ install(TARGETS 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}
+ BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
+ if(BUILD_EXECUTABLE)
+ install(TARGETS 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}
+ BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
+ endif()
+ 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"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
- COMPONENT Devel
-)
+ COMPATIBILITY SameMajorVersion
+ )
+ install(
+ FILES
+ "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
+ "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
+ COMPONENT Devel
+ )
+endif()
diff --git a/METADATA b/METADATA
index ab7bdf7..ceb1712 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/cpu_features.git"
}
- version: "v0.8.0"
+ version: "v0.9.0"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 4
- day: 27
+ month: 9
+ day: 14
}
}
diff --git a/README.md b/README.md
index ee0ce70..4e66497 100644
--- a/README.md
+++ b/README.md
@@ -7,36 +7,44 @@ instructions) at runtime.
[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/)
-| Os | amd64 | AArch64 | ARM | MIPS | POWER | RISCV | s390x |
-| :-- | --: | --: | --: | --: | --: | --: | --: |
-| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] | [![][i1g0]][l1g0]<br/>![][d1] |
-| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
-| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
-| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
-
-[d0]: https://img.shields.io/badge/CMake-N%2FA-lightgrey
-[d1]: https://img.shields.io/badge/Bazel-N%2FA-lightgrey
-[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&label=CMake
-[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&label=Bazel
-[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&label=CMake
-[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&label=CMake
-[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&label=CMake
-[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&label=CMake
-[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&label=CMake
-[i1g0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&label=CMake
-[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&label=CMake
-[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&label=CMake
-[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&label=CMake
+| | Linux | FreeBSD | MacOS | Windows |
+| :-- | --: | --: | --: | --: |
+| amd64 | [![CMake][i1a0]][l1a0]<br/>[![Bazel][i1a1]][l1a1] | [![CMake][i2a0]][l2a0]<br/>![Bazel][d1] | [![CMake][i3a0]][l3a0]<br/>[![Bazel][i3a1]][l3a1] | [![CMake][i4a0]][l4a0]<br/>![Bazel][d1] |
+| AArch64 | [![CMake][i1b0]][l1b0]<br/>[![Bazel][i1b1]][l1b1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| ARM | [![CMake][i1c0]][l1c0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| MIPS | [![CMake][i1d0]][l1d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| POWER | [![CMake][i1e0]][l1e0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| RISCV | [![CMake][i1f0]][l1f0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| LOONGARCH | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+| s390x | [![CMake][i1h0]][l1h0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
+
+[d0]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=cmake
+[d1]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
+[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
+[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1b1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
+[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i1h0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&event=push&label=&logo=cmake
+[i3a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
+[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&event=push&label=&logo=cmake
[l1a0]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_cmake.yml
[l1a1]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_bazel.yml
[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml
+[l1b1]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_bazel.yml
[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml
[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml
[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml
-[l1g0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
+[l1h0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml
[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml
+[l3a1]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_bazel.yml
[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml
## Table of Contents
@@ -178,14 +186,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
<a name="support"></a>
## What's supported
-| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | s390x |
-|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
-| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
-| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet |
-| MacOs | yes² | not yet | N/A | N/A | no | N/A | no |
-| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A |
-| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A |
-| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A |
+| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | Loongarch | s390x |
+|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:---------:|:-------:|
+| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
+| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | not yet |
+| MacOs | yes² | yes⁵ | N/A | N/A | N/A | N/A | N/A | N/A |
+| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | N/A |
+| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | N/A |
+| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | N/A |
1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
@@ -200,6 +208,8 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
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.
+5. **Features revealed from sysctl.** features are retrieved by the `sysctl`
+ instruction.
<a name="ndk"></a>
## Android NDK's drop in replacement
diff --git a/bazel/ci/Makefile b/bazel/ci/Makefile
new file mode 100644
index 0000000..1967213
--- /dev/null
+++ b/bazel/ci/Makefile
@@ -0,0 +1,122 @@
+PROJECT := cpu_features
+BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
+SHA1 := $(shell git rev-parse --verify HEAD)
+
+# General commands
+.PHONY: help
+BOLD=\e[1m
+RESET=\e[0m
+
+help:
+ @echo -e "${BOLD}SYNOPSIS${RESET}"
+ @echo -e "\tmake <target> [NOCACHE=1]"
+ @echo
+ @echo -e "${BOLD}DESCRIPTION${RESET}"
+ @echo -e "\ttest build inside docker container to have a reproductible build."
+ @echo
+ @echo -e "${BOLD}MAKE TARGETS${RESET}"
+ @echo -e "\t${BOLD}help${RESET}: display this help and exit."
+ @echo
+ @echo -e "\t${BOLD}<platform>_<stage>${RESET}: build <stage> docker image using an Ubuntu:latest x86_64 base image."
+ @echo -e "\t${BOLD}save_<platform>_<stage>${RESET}: Save the <stage> docker image."
+ @echo -e "\t${BOLD}sh_<platform>_<stage>${RESET}: run a container using the <stage> docker image (debug purpose)."
+ @echo -e "\t${BOLD}clean_<platform>_<stage>${RESET}: Remove cache and docker image."
+ @echo
+ @echo -e "\tWith ${BOLD}<platform>${RESET}:"
+ @echo -e "\t\t${BOLD}amd64${RESET} (linux/amd64)"
+ @echo -e "\t\t${BOLD}arm64${RESET} (linux/arm64)"
+ @echo
+ @echo -e "\tWith ${BOLD}<stage>${RESET}:"
+ @echo -e "\t\t${BOLD}env${RESET}"
+ @echo -e "\t\t${BOLD}devel${RESET}"
+ @echo -e "\t\t${BOLD}build${RESET}"
+ @echo -e "\t\t${BOLD}test${RESET}"
+ @echo -e "\te.g. 'make amd64_build'"
+ @echo
+ @echo -e "\t${BOLD}clean${RESET}: Remove cache and ALL docker images."
+ @echo
+ @echo -e "\t${BOLD}NOCACHE=1${RESET}: use 'docker build --no-cache' when building container (default use cache)."
+ @echo -e "\t${BOLD}VERBOSE=1${RESET}: use 'docker build --progress=plain' when building container."
+ @echo
+ @echo -e "branch: $(BRANCH)"
+ @echo -e "sha1: $(SHA1)"
+
+# Need to add cmd_platform to PHONY otherwise target are ignored since they do not
+# contain recipe (using FORCE do not work here)
+.PHONY: all
+all: build
+
+# Delete all implicit rules to speed up makefile
+MAKEFLAGS += --no-builtin-rules
+.SUFFIXES:
+# Remove some rules from gmake that .SUFFIXES does not remove.
+SUFFIXES =
+# Keep all intermediate files
+# ToDo: try to remove it later
+.SECONDARY:
+
+# Docker image name prefix.
+IMAGE := ${PROJECT}
+
+DOCKER_BUILDX_CMD := docker buildx build
+ifdef NOCACHE
+DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --no-cache
+endif
+ifdef VERBOSE
+DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --progress=plain
+endif
+DOCKER_RUN_CMD := docker run --rm --init --net=host
+
+############
+## NATIVE ##
+############
+# ref: https://go.dev/doc/install/source#environment
+# ref: https://github.com/containerd/containerd/blob/269548fa27e0089a8b8278fc4fc781d7f65a939b/platforms/platforms.go#L80-L94
+PLATFORMS := amd64 arm64
+STAGES := env devel build test
+
+define make-platform-stage-target =
+$1_$2: docker/Dockerfile
+ ${DOCKER_BUILDX_CMD} \
+ --platform linux/$1 \
+ --build-arg PLATFORM="$1" \
+ --target=$2 \
+ --tag ${IMAGE}:$1_$2 \
+ -f $$< ../..
+
+save_$1_$2: cache/$1/docker_$2.tar
+cache/$1/docker_$2.tar: $1_$2
+ @rm -f $$@
+ mkdir -p cache/$1
+ docker save ${IMAGE}:$1_$2 -o $$@
+
+sh_$1_$2: $1_$2
+ ${DOCKER_RUN_CMD} --platform linux/$1 -it --name ${IMAGE}_$1_$2 ${IMAGE}:$1_$2
+
+clean_$1_$2:
+ docker image rm -f ${IMAGE}:$1_$2 2>/dev/null
+ rm -f cache/$1/docker_$2.tar
+endef
+
+define make-platform-target =
+$(foreach stage,$(STAGES),$(eval $(call make-platform-stage-target,$1,$(stage))))
+
+# merge
+.PHONY: clean_$1
+clean_$1: $(addprefix clean_$1_, $(STAGES))
+ -rmdir cache/$1
+endef
+
+$(foreach platform,$(PLATFORMS),$(eval $(call make-platform-target,$(platform))))
+
+## MERGE ##
+.PHONY: clean
+clean: $(addprefix clean_, $(PLATFORMS))
+ docker container prune -f
+ docker image prune -f
+ -rmdir cache
+
+.PHONY: distclean
+distclean: clean
+ -docker container rm -f $$(docker container ls -aq)
+ -docker image rm -f $$(docker image ls -aq)
diff --git a/bazel/ci/docker/Dockerfile b/bazel/ci/docker/Dockerfile
new file mode 100644
index 0000000..a46b493
--- /dev/null
+++ b/bazel/ci/docker/Dockerfile
@@ -0,0 +1,37 @@
+# Create a virtual environment with all tools installed
+# ref: https://hub.docker.com/_/ubuntu
+FROM ubuntu:latest AS env
+
+# Install system build dependencies
+ENV PATH=/usr/local/bin:$PATH
+RUN apt-get update -qq \
+&& DEBIAN_FRONTEND=noninteractive apt-get install -yq \
+ git wget build-essential \
+&& apt-get clean \
+&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+ENTRYPOINT ["/usr/bin/bash", "-c"]
+CMD ["/usr/bin/bash"]
+
+# Install Bazelisk
+ARG PLATFORM
+RUN wget \
+ "https://github.com/bazelbuild/bazelisk/releases/download/v1.18.0/bazelisk-linux-${PLATFORM}" \
+&& chmod +x "bazelisk-linux-${PLATFORM}" \
+&& mv "bazelisk-linux-${PLATFORM}" /usr/local/bin/bazel
+
+FROM env AS devel
+WORKDIR /home/project
+COPY . .
+
+FROM devel AS build
+RUN bazel version
+RUN bazel build \
+ -c opt \
+ --subcommands=true \
+ ...
+
+FROM build AS test
+RUN bazel test \
+ -c opt \
+ --test_output=errors \
+ ...
diff --git a/bazel/platforms.bzl b/bazel/platforms.bzl
index 5671add..eb025ce 100644
--- a/bazel/platforms.bzl
+++ b/bazel/platforms.bzl
@@ -9,3 +9,10 @@ PLATFORM_CPU_ARM64 = ("@platforms//cpu:arm64")
PLATFORM_CPU_MIPS = ("@platforms//cpu:mips64")
PLATFORM_CPU_PPC = ("@platforms//cpu:ppc")
+
+PLATFORM_CPU_RISCV32 = ("@platforms//cpu:riscv32")
+
+PLATFORM_CPU_RISCV64 = ("@platforms//cpu:riscv64")
+
+
+PLATFORM_OS_MACOS = ("@platforms//os:macos")
diff --git a/cmake/README.md b/cmake/README.md
index de33b23..feaa2fb 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -17,7 +17,7 @@ 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 `CpuFeature::cpu_features` target to the `target_link_libraries()` section of
+3- Add the `CpuFeatures::cpu_features` target to the `target_link_libraries()` section of
your executable or of your library.
## Disabling tests
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index 215b567..4fe7c3d 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -83,6 +83,10 @@
#define CPU_FEATURES_ARCH_RISCV128
#endif
+#if defined(__loongarch64)
+#define CPU_FEATURES_ARCH_LOONGARCH
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Os
////////////////////////////////////////////////////////////////////////////////
diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h
index d124b5f..18a3313 100644
--- a/include/cpuinfo_aarch64.h
+++ b/include/cpuinfo_aarch64.h
@@ -169,6 +169,27 @@ typedef struct {
int ecv : 1; // Enhanced counter virtualization.
int afp : 1; // Alternate floating-point behaviour.
int rpres : 1; // 12-bit reciprocal (square root) estimate precision.
+ int mte3 : 1; // MTE asymmetric fault handling.
+ int sme : 1; // Scalable Matrix Extension.
+ int smei16i64 : 1; // 16-bit to 64-bit integer widening outer product.
+ int smef64f64 : 1; // FP64 to FP64 outer product.
+ int smei8i32 : 1; // 8-bit to 32-bit integer widening outer product.
+ int smef16f32 : 1; // FP16 to FP32 outer product.
+ int smeb16f32 : 1; // BFloat16 to FP32 outper product.
+ int smef32f32 : 1; // FP32 to FP32 outer product.
+ int smefa64 : 1; // Full A64 support for SME in streaming mode.
+ int wfxt : 1; // WFE and WFI with timeout.
+ int ebf16 : 1; // Extended BFloat16 instructions.
+ int sveebf16 : 1; // SVE BFloat16 instructions.
+ int cssc : 1; // Common short sequence compression instructions.
+ int rprfm : 1; // Range Prefetch Memory hint instruction.
+ int sve2p1 : 1; // Scalable Vector Extension (version 2.1).
+ int sme2 : 1; // Scalable Matrix Extension (version 2).
+ int sme2p1 : 1; // Scalable Matrix Extension (version 2.1).
+ int smei16i32 : 1; // 16-bit to 64-bit integer widening outer product.
+ int smebi32i32 : 1; // 1-bit binary to 32-bit integer outer product.
+ int smeb16b16 : 1; // SME2.1 BFloat16 instructions.
+ int smef16f16 : 1; // FP16 to FP16 outer product.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
@@ -242,6 +263,27 @@ typedef enum {
AARCH64_ECV,
AARCH64_AFP,
AARCH64_RPRES,
+ AARCH64_MTE3,
+ AARCH64_SME,
+ AARCH64_SME_I16I64,
+ AARCH64_SME_F64F64,
+ AARCH64_SME_I8I32,
+ AARCH64_SME_F16F32,
+ AARCH64_SME_B16F32,
+ AARCH64_SME_F32F32,
+ AARCH64_SME_FA64,
+ AARCH64_WFXT,
+ AARCH64_EBF16,
+ AARCH64_SVE_EBF16,
+ AARCH64_CSSC,
+ AARCH64_RPRFM,
+ AARCH64_SVE2P1,
+ AARCH64_SME2,
+ AARCH64_SME2P1,
+ AARCH64_SME_I16I32,
+ AARCH64_SME_BI32I32,
+ AARCH64_SME_B16B16,
+ AARCH64_SME_F16F16,
AARCH64_LAST_,
} Aarch64FeaturesEnum;
diff --git a/include/cpuinfo_loongarch.h b/include/cpuinfo_loongarch.h
new file mode 100644
index 0000000..d166223
--- /dev/null
+++ b/include/cpuinfo_loongarch.h
@@ -0,0 +1,77 @@
+// Copyright 2023 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_LOONGARCH_H_
+#define CPU_FEATURES_INCLUDE_CPUINFO_LOONGARCH_H_
+
+#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
+
+#if !defined(CPU_FEATURES_ARCH_LOONGARCH)
+#error "Including cpuinfo_loongarch.h from a non-loongarch target."
+#endif
+
+CPU_FEATURES_START_CPP_NAMESPACE
+
+typedef struct {
+ // Base
+ int CPUCFG : 1; // Instruction for Identify CPU Features
+
+ // Extension
+ int LAM : 1; // Extension for Atomic Memory Access Instructions
+ int UAL : 1; // Extension for Non-Aligned Memory Access
+ int FPU : 1; // Extension for Basic Floating-Point Instructions
+ int LSX : 1; // Extension for Loongson SIMD eXtension
+ int LASX : 1; // Extension for Loongson Advanced SIMD eXtension
+ int CRC32 : 1; // Extension for Cyclic Redundancy Check Instructions
+ int COMPLEX : 1; // Extension for Complex Vector Operation Instructions
+ int CRYPTO : 1; // Extension for Encryption And Decryption Vector Instructions
+ int LVZ : 1; // Extension for Virtualization
+ int LBT_X86 : 1; // Extension for X86 Binary Translation Extension
+ int LBT_ARM : 1; // Extension for ARM Binary Translation Extension
+ int LBT_MIPS : 1; // Extension for MIPS Binary Translation Extension
+ int PTW : 1; // Extension for Page Table Walker
+
+} LoongArchFeatures;
+
+typedef struct {
+ LoongArchFeatures features;
+} LoongArchInfo;
+
+typedef enum {
+ LOONGARCH_CPUCFG,
+ LOONGARCH_LAM,
+ LOONGARCH_UAL,
+ LOONGARCH_FPU,
+ LOONGARCH_LSX,
+ LOONGARCH_LASX,
+ LOONGARCH_CRC32,
+ LOONGARCH_COMPLEX,
+ LOONGARCH_CRYPTO,
+ LOONGARCH_LVZ,
+ LOONGARCH_LBT_X86,
+ LOONGARCH_LBT_ARM,
+ LOONGARCH_LBT_MIPS,
+ LOONGARCH_PTW,
+ LOONGARCH_LAST_,
+} LoongArchFeaturesEnum;
+
+LoongArchInfo GetLoongArchInfo(void);
+int GetLoongArchFeaturesEnumValue(const LoongArchFeatures* features,
+ LoongArchFeaturesEnum value);
+const char* GetLoongArchFeaturesEnumName(LoongArchFeaturesEnum);
+
+CPU_FEATURES_END_CPP_NAMESPACE
+
+#endif // CPU_FEATURES_INCLUDE_CPUINFO_LOONGARCH_H_
diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h
index e897500..796d3f3 100644
--- a/include/cpuinfo_x86.h
+++ b/include/cpuinfo_x86.h
@@ -86,6 +86,7 @@ typedef struct {
int amx_bf16 : 1;
int amx_tile : 1;
int amx_int8 : 1;
+ int amx_fp16 : 1;
int pclmulqdq : 1;
int smx : 1;
@@ -107,6 +108,9 @@ typedef struct {
int fz_rep_movsb : 1; // Fast zero-length REP MOVSB
int fs_rep_stosb : 1; // Fast short REP STOSB
int fs_rep_cmpsb_scasb : 1; // Fast short REP CMPSB/SCASB
+
+ int lam: 1; // Intel Linear Address Mask
+ int uai: 1; // AMD Upper Address Ignore
// Make sure to update X86FeaturesEnum below if you add a field here.
} X86Features;
@@ -251,6 +255,7 @@ typedef enum {
X86_AMX_BF16,
X86_AMX_TILE,
X86_AMX_INT8,
+ X86_AMX_FP16,
X86_PCLMULQDQ,
X86_SMX,
X86_SGX,
@@ -270,6 +275,8 @@ typedef enum {
X86_FZ_REP_MOVSB,
X86_FS_REP_STOSB,
X86_FS_REP_CMPSB_SCASB,
+ X86_LAM,
+ X86_UAI,
X86_LAST_,
} X86FeaturesEnum;
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index 3290cc9..59e1657 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -83,6 +83,27 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define AARCH64_HWCAP2_ECV (1UL << 19)
#define AARCH64_HWCAP2_AFP (1UL << 20)
#define AARCH64_HWCAP2_RPRES (1UL << 21)
+#define AARCH64_HWCAP2_MTE3 (1UL << 22)
+#define AARCH64_HWCAP2_SME (1UL << 23)
+#define AARCH64_HWCAP2_SME_I16I64 (1UL << 24)
+#define AARCH64_HWCAP2_SME_F64F64 (1UL << 25)
+#define AARCH64_HWCAP2_SME_I8I32 (1UL << 26)
+#define AARCH64_HWCAP2_SME_F16F32 (1UL << 27)
+#define AARCH64_HWCAP2_SME_B16F32 (1UL << 28)
+#define AARCH64_HWCAP2_SME_F32F32 (1UL << 29)
+#define AARCH64_HWCAP2_SME_FA64 (1UL << 30)
+#define AARCH64_HWCAP2_WFXT (1UL << 31)
+#define AARCH64_HWCAP2_EBF16 (1UL << 32)
+#define AARCH64_HWCAP2_SVE_EBF16 (1UL << 33)
+#define AARCH64_HWCAP2_CSSC (1UL << 34)
+#define AARCH64_HWCAP2_RPRFM (1UL << 35)
+#define AARCH64_HWCAP2_SVE2P1 (1UL << 36)
+#define AARCH64_HWCAP2_SME2 (1UL << 37)
+#define AARCH64_HWCAP2_SME2P1 (1UL << 38)
+#define AARCH64_HWCAP2_SME_I16I32 (1UL << 39)
+#define AARCH64_HWCAP2_SME_BI32I32 (1UL << 40)
+#define AARCH64_HWCAP2_SME_B16B16 (1UL << 41)
+#define AARCH64_HWCAP2_SME_F16F16 (1UL << 42)
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#define ARM_HWCAP_SWP (1UL << 0)
@@ -216,6 +237,22 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
#define RISCV_HWCAP_V (1UL << ('V' - 'A'))
+// https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h
+#define HWCAP_LOONGARCH_CPUCFG (1 << 0)
+#define HWCAP_LOONGARCH_LAM (1 << 1)
+#define HWCAP_LOONGARCH_UAL (1 << 2)
+#define HWCAP_LOONGARCH_FPU (1 << 3)
+#define HWCAP_LOONGARCH_LSX (1 << 4)
+#define HWCAP_LOONGARCH_LASX (1 << 5)
+#define HWCAP_LOONGARCH_CRC32 (1 << 6)
+#define HWCAP_LOONGARCH_COMPLEX (1 << 7)
+#define HWCAP_LOONGARCH_CRYPTO (1 << 8)
+#define HWCAP_LOONGARCH_LVZ (1 << 9)
+#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
+#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
+#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
+#define HWCAP_LOONGARCH_PTW (1 << 13)
+
typedef struct {
unsigned long hwcaps;
unsigned long hwcaps2;
diff --git a/scripts/generate_badges.d b/scripts/generate_badges.d
index bf5aa54..e5037ef 100644..100755
--- a/scripts/generate_badges.d
+++ b/scripts/generate_badges.d
@@ -1,11 +1,23 @@
+#!/usr/bin/env -S docker run --rm -v ${PWD}/scripts:/scripts -v ${PWD}/.github/workflows:/.github/workflows dlanguage/dmd dmd -run /scripts/generate_badges.d
+
+// To run this script:
+// cd /path/to/cpu_features
+// ./scripts/generate_badges.d
+
import std.algorithm : each, map, cartesianProduct, filter, joiner, sort, uniq;
-import std.array : array;
+import std.array;
+import std.base64 : Base64;
import std.conv : to;
+import std.file : exists;
import std.format;
import std.range : chain, only;
import std.stdio;
+import std.string : representation;
import std.traits : EnumMembers;
+immutable string bazel_svg = `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6 .16l5.786 5.786L6 11.732.214 5.946 6 .161zM0 6.214V12l5.786 5.786V12L0 6.214zM18 .16l5.786 5.786L18 11.732l-5.786-5.786L18 .161zM24 6.214V12l-5.786 5.786V12L24 6.214zM12 6.16l5.786 5.786L12 17.732l-5.786-5.786L12 6.161zM11.84 18.054v5.785l-5.786-5.785v-5.786l5.785 5.786zM12.16 18.054l5.786-5.786v5.786l-5.785 5.785v-5.785z" stroke="transparent" fill="white"/></svg>`;
+const string bazel_svg_base64 = Base64.encode(representation(bazel_svg));
+
enum BuildSystem
{
CMake,
@@ -20,6 +32,7 @@ enum Cpu
MIPS,
POWER,
RISCV,
+ LOONGARCH,
s390x,
}
@@ -39,14 +52,11 @@ const:
Os os;
BuildSystem build_system;
+private:
string id()
{
- return format("%d%c%d", cast(uint)(os) + 1, cast(char)('a' + cpu), cast(uint)(build_system));
- }
-
- string disabled_image_ref()
- {
- return format("[d%d]", cast(uint)(build_system));
+ return format("%d%c%d", cast(uint)(os) + 1, cast(char)('a' + cpu),
+ cast(uint)(build_system));
}
string link_ref()
@@ -59,80 +69,94 @@ const:
return format("[i%s]", id());
}
+ string filename()
+ {
+ import std.uni : toLower;
+
+ return toLower(format("%s_%s_%s.yml", cpu, os, build_system));
+ }
+
bool enabled()
{
+ return exists("../.github/workflows/" ~ filename());
+ }
+
+ string append_logo(string url)
+ {
final switch (build_system)
{
case BuildSystem.CMake:
- return os == Os.Linux || cpu == Cpu.amd64;
+ return url ~ "&logo=cmake";
case BuildSystem.Bazel:
- return os == Os.Linux && cpu == Cpu.amd64;
+ return url ~ "&logo=data:image/svg%2bxml;base64," ~ bazel_svg_base64;
}
}
- string text()
+public:
+
+ string disabled_image_ref()
{
- if (enabled())
- return format("[![]%s]%s", image_ref, link_ref);
- return format("![]%s", disabled_image_ref);
+ return format("[d%d]", cast(uint)(build_system));
}
- string disabled_image_link()
+ string text()
{
- return format("%s: https://img.shields.io/badge/%s-N%%2FA-lightgrey", disabled_image_ref, build_system);
+ if (enabled())
+ return format("[![%s]%s]%s", build_system, image_ref, link_ref);
+ return format("![%s]%s", build_system, disabled_image_ref);
}
- string filename()
+ string disabled_image_link()
{
- import std.uni : toLower;
-
- return toLower(format("%s_%s_%s.yml", cpu, os, build_system));
+ return append_logo(format("%s: https://img.shields.io/badge/n%%2Fa-lightgrey?",
+ disabled_image_ref));
}
string link_decl()
{
- return format("%s: https://github.com/google/cpu_features/actions/workflows/%s", link_ref, filename());
+ return format("%s: https://github.com/google/cpu_features/actions/workflows/%s",
+ link_ref, filename());
}
string image_decl()
{
- return format(
- "%s: https://img.shields.io/github/actions/workflow/status/google/cpu_features/%s?branch=main&label=%s", image_ref, filename(), build_system);
+ return append_logo(format("%s: https://img.shields.io/github/actions/workflow/status/google/cpu_features/%s?branch=main&event=push&label=",
+ image_ref, filename()));
}
+
}
-auto tableHeader(in Cpu[] cpus)
+auto tableHeader(in Os[] oses)
{
- return chain(only("Os"), cpus.map!(to!string)).array;
+ return chain(only(""), oses.map!(to!string)).array;
}
-auto tableAlignment(in Cpu[] cpus)
+auto tableAlignment(in Os[] oses)
{
- return chain(only(":--"), cpus.map!(v => "--:")).array;
+ return chain(only(":--"), oses.map!(v => "--:")).array;
}
auto tableCell(Range)(in Os os, in Cpu cpu, Range badges)
{
- return badges
- .filter!(b => b.cpu == cpu && b.os == os)
+ return badges.filter!(b => b.cpu == cpu && b.os == os)
.map!(b => b.text())
- .joiner("<br/>")
- .to!string;
+ .joiner("<br/>").to!string;
}
-auto tableRow(Range)(in Os os, in Cpu[] cpus, Range badges)
+auto tableRow(Range)(in Cpu cpu, in Os[] oses, Range badges)
{
- return chain(only(os.to!string), cpus.map!(cpu => tableCell(os, cpu, badges))).array;
+ return chain(only(cpu.to!string), oses.map!(os => tableCell(os, cpu, badges))).array;
}
auto tableRows(Range)(in Os[] oses, in Cpu[] cpus, Range badges)
{
- return oses.map!(os => tableRow(os, cpus, badges)).array;
+ return cpus.map!(cpu => tableRow(cpu, oses, badges)).array;
}
auto table(Range)(in Os[] oses, in Cpu[] cpus, Range badges)
{
- return chain(only(tableHeader(cpus)), only(tableAlignment(cpus)), tableRows(oses, cpus, badges));
+ return chain(only(tableHeader(oses)), only(tableAlignment(oses)),
+ tableRows(oses, cpus, badges));
}
void main()
@@ -140,26 +164,17 @@ void main()
immutable allCpus = [EnumMembers!Cpu];
immutable allOses = [EnumMembers!Os];
immutable allBuildSystems = [EnumMembers!BuildSystem];
-
auto badges = cartesianProduct(allCpus, allOses, allBuildSystems).map!(
t => Badge(t[0], t[1], t[2]));
-
writefln("%(|%-( %s |%) |\n%) |", table(allOses, allCpus, badges));
writeln();
- badges
- .filter!(b => !b.enabled)
+ badges.filter!(b => !b.enabled)
.map!(b => b.disabled_image_link())
.array
.sort
.uniq
.each!writeln;
-
- badges
- .filter!(b => b.enabled)
+ badges.filter!(b => b.enabled)
.map!(b => [b.link_decl(), b.image_decl()])
- .joiner()
- .array
- .sort
- .uniq
- .each!writeln;
+ .joiner().array.sort.uniq.each!writeln;
}
diff --git a/src/impl_aarch64__base_implementation.inl b/src/impl_aarch64__base_implementation.inl
new file mode 100644
index 0000000..ccc6c11
--- /dev/null
+++ b/src/impl_aarch64__base_implementation.inl
@@ -0,0 +1,118 @@
+// Copyright 2021 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 <stdbool.h>
+
+#include "cpu_features_macros.h"
+#include "cpuinfo_aarch64.h"
+#include "internal/bit_utils.h"
+#include "internal/filesystem.h"
+#include "internal/stack_line_reader.h"
+#include "internal/string_view.h"
+
+#if !defined(CPU_FEATURES_ARCH_AARCH64)
+#error "Cannot compile aarch64_base on a non aarch64 platform."
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
+ LINE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
+ LINE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
+ LINE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
+ LINE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
+ LINE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
+ LINE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
+ LINE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
+ LINE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
+ LINE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
+ LINE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
+ LINE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
+ LINE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
+ LINE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
+ LINE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
+ LINE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
+ LINE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
+ LINE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
+ LINE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
+ LINE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
+ LINE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
+ LINE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
+ LINE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
+ LINE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
+ LINE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
+ LINE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
+ LINE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
+ LINE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
+ LINE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
+ LINE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
+ LINE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
+ LINE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
+ LINE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
+ LINE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
+ LINE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
+ LINE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
+ LINE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
+ AARCH64_HWCAP2_SVEBITPERM) \
+ LINE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
+ LINE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
+ LINE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
+ LINE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
+ LINE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
+ LINE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
+ LINE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
+ LINE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
+ LINE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
+ LINE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
+ LINE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
+ LINE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
+ LINE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) \
+ LINE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE) \
+ LINE(AARCH64_ECV, ecv, "ecv", 0, AARCH64_HWCAP2_ECV) \
+ LINE(AARCH64_AFP, afp, "afp", 0, AARCH64_HWCAP2_AFP) \
+ LINE(AARCH64_RPRES, rpres, "rpres", 0, AARCH64_HWCAP2_RPRES) \
+ LINE(AARCH64_MTE3, mte3, "mte3", 0, AARCH64_HWCAP2_MTE3) \
+ LINE(AARCH64_SME, sme, "sme", 0, AARCH64_HWCAP2_SME) \
+ LINE(AARCH64_SME_I16I64, smei16i64, "smei16i64", 0, \
+ AARCH64_HWCAP2_SME_I16I64) \
+ LINE(AARCH64_SME_F64F64, smef64f64, "smef64f64", 0, \
+ AARCH64_HWCAP2_SME_F64F64) \
+ LINE(AARCH64_SME_I8I32, smei8i32, "smei8i32", 0, AARCH64_HWCAP2_SME_I8I32) \
+ LINE(AARCH64_SME_F16F32, smef16f32, "smef16f32", 0, \
+ AARCH64_HWCAP2_SME_F16F32) \
+ LINE(AARCH64_SME_B16F32, smeb16f32, "smeb16f32", 0, \
+ AARCH64_HWCAP2_SME_B16F32) \
+ LINE(AARCH64_SME_F32F32, smef32f32, "smef32f32", 0, \
+ AARCH64_HWCAP2_SME_F32F32) \
+ LINE(AARCH64_SME_FA64, smefa64, "smefa64", 0, AARCH64_HWCAP2_SME_FA64) \
+ LINE(AARCH64_WFXT, wfxt, "wfxt", 0, AARCH64_HWCAP2_WFXT) \
+ LINE(AARCH64_EBF16, ebf16, "ebf16", 0, AARCH64_HWCAP2_EBF16) \
+ LINE(AARCH64_SVE_EBF16, sveebf16, "sveebf16", 0, AARCH64_HWCAP2_SVE_EBF16) \
+ LINE(AARCH64_CSSC, cssc, "cssc", 0, AARCH64_HWCAP2_CSSC) \
+ LINE(AARCH64_RPRFM, rprfm, "rprfm", 0, AARCH64_HWCAP2_RPRFM) \
+ LINE(AARCH64_SVE2P1, sve2p1, "sve2p1", 0, AARCH64_HWCAP2_SVE2P1) \
+ LINE(AARCH64_SME2, sme2, "sme2", 0, AARCH64_HWCAP2_SME2) \
+ LINE(AARCH64_SME2P1, sme2p1, "sme2p1", 0, AARCH64_HWCAP2_SME2P1) \
+ LINE(AARCH64_SME_I16I32, smei16i32, "smei16i32", 0, \
+ AARCH64_HWCAP2_SME_I16I32) \
+ LINE(AARCH64_SME_BI32I32, smebi32i32, "smebi32i32", 0, \
+ AARCH64_HWCAP2_SME_BI32I32) \
+ LINE(AARCH64_SME_B16B16, smeb16b16, "smeb16b16", 0, \
+ AARCH64_HWCAP2_SME_B16B16) \
+ LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, AARCH64_HWCAP2_SME_F16F16)
+#define INTROSPECTION_PREFIX Aarch64
+#define INTROSPECTION_ENUM_PREFIX AARCH64
+#include "define_introspection_and_hwcaps.inl"
diff --git a/src/impl_aarch64_linux_or_android.c b/src/impl_aarch64_linux_or_android.c
index ef923d9..c0a764c 100644
--- a/src/impl_aarch64_linux_or_android.c
+++ b/src/impl_aarch64_linux_or_android.c
@@ -17,81 +17,7 @@
#ifdef CPU_FEATURES_ARCH_AARCH64
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
-#include "cpuinfo_aarch64.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// Definitions for introspection.
-////////////////////////////////////////////////////////////////////////////////
-#define INTROSPECTION_TABLE \
- LINE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
- LINE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
- LINE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
- LINE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
- LINE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
- LINE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
- LINE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
- LINE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
- LINE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
- LINE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
- LINE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
- LINE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
- LINE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
- LINE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
- LINE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
- LINE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
- LINE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
- LINE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
- LINE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
- LINE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
- LINE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
- LINE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
- LINE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
- LINE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
- LINE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
- LINE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
- LINE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
- LINE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
- LINE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
- LINE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
- LINE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
- LINE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
- LINE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
- LINE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
- LINE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
- LINE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
- LINE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
- AARCH64_HWCAP2_SVEBITPERM) \
- LINE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
- LINE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
- LINE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
- LINE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
- LINE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
- LINE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
- LINE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
- LINE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
- LINE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
- LINE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
- LINE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
- LINE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
- LINE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) \
- LINE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE) \
- LINE(AARCH64_ECV, ecv, "ecv", 0, AARCH64_HWCAP2_ECV) \
- LINE(AARCH64_AFP, afp, "afp", 0, AARCH64_HWCAP2_AFP) \
- LINE(AARCH64_RPRES, rpres, "rpres", 0, AARCH64_HWCAP2_RPRES)
-#define INTROSPECTION_PREFIX Aarch64
-#define INTROSPECTION_ENUM_PREFIX AARCH64
-#include "define_introspection_and_hwcaps.inl"
-
-////////////////////////////////////////////////////////////////////////////////
-// Implementation.
-////////////////////////////////////////////////////////////////////////////////
-
-#include <stdbool.h>
-
-#include "internal/bit_utils.h"
-#include "internal/filesystem.h"
-#include "internal/stack_line_reader.h"
-#include "internal/string_view.h"
+#include "impl_aarch64__base_implementation.inl"
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info) {
diff --git a/src/impl_aarch64_macos_or_iphone.c b/src/impl_aarch64_macos_or_iphone.c
new file mode 100644
index 0000000..7b97896
--- /dev/null
+++ b/src/impl_aarch64_macos_or_iphone.c
@@ -0,0 +1,88 @@
+// Copyright 2021 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 "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_AARCH64
+#if defined(CPU_FEATURES_OS_MACOS) || defined(CPU_FEATURES_OS_IPHONE)
+
+#include "impl_aarch64__base_implementation.inl"
+
+#if !defined(HAVE_SYSCTLBYNAME)
+#error "Darwin needs support for sysctlbyname"
+#endif
+#include <sys/sysctl.h>
+
+#if defined(CPU_FEATURES_MOCK_SYSCTL_AARCH64)
+extern bool GetDarwinSysCtlByName(const char*);
+extern int GetDarwinSysCtlByNameValue(const char* name);
+#else
+static int GetDarwinSysCtlByNameValue(const char* name) {
+ int enabled;
+ size_t enabled_len = sizeof(enabled);
+ const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0);
+ return failure ? 0 : enabled;
+}
+
+static bool GetDarwinSysCtlByName(const char* name) {
+ return GetDarwinSysCtlByNameValue(name) != 0;
+}
+#endif
+
+static const Aarch64Info kEmptyAarch64Info;
+
+Aarch64Info GetAarch64Info(void) {
+ Aarch64Info info = kEmptyAarch64Info;
+
+ // Handling Darwin platform through sysctlbyname.
+ info.implementer = GetDarwinSysCtlByNameValue("hw.cputype");
+ info.variant = GetDarwinSysCtlByNameValue("hw.cpusubtype");
+ info.part = GetDarwinSysCtlByNameValue("hw.cpufamily");
+ info.revision = GetDarwinSysCtlByNameValue("hw.cpusubfamily");
+
+ info.features.fp = GetDarwinSysCtlByName("hw.optional.floatingpoint");
+ info.features.asimd = GetDarwinSysCtlByName("hw.optional.AdvSIMD");
+ info.features.aes = GetDarwinSysCtlByName("hw.optional.arm.FEAT_AES");
+ info.features.pmull = GetDarwinSysCtlByName("hw.optional.arm.FEAT_PMULL");
+ info.features.sha1 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA1");
+ info.features.sha2 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA256");
+ info.features.crc32 = GetDarwinSysCtlByName("hw.optional.armv8_crc32");
+ info.features.atomics = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE");
+ info.features.fphp = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FP16");
+ info.features.asimdhp = GetDarwinSysCtlByName("hw.optional.arm.AdvSIMD_HPFPCvt");
+ info.features.asimdrdm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_RDM");
+ info.features.jscvt = GetDarwinSysCtlByName("hw.optional.arm.FEAT_JSCVT");
+ info.features.fcma = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FCMA");
+ info.features.lrcpc = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LRCPC");
+ info.features.dcpop = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DPB");
+ info.features.sha3 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA3");
+ info.features.asimddp = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DotProd");
+ info.features.sha512 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA512");
+ info.features.asimdfhm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FHM");
+ info.features.dit = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DIT");
+ info.features.uscat = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE2");
+ info.features.flagm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FlagM");
+ info.features.ssbs = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SSBS");
+ info.features.sb = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SB");
+ info.features.flagm2 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FlagM2");
+ info.features.frint = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FRINTTS");
+ info.features.i8mm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_I8MM");
+ info.features.bf16 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_BF16");
+ info.features.bti = GetDarwinSysCtlByName("hw.optional.arm.FEAT_BTI");
+
+ return info;
+}
+
+#endif // defined(CPU_FEATURES_OS_MACOS) || defined(CPU_FEATURES_OS_IPHONE)
+#endif // CPU_FEATURES_ARCH_AARCH64
diff --git a/src/impl_loongarch_linux.c b/src/impl_loongarch_linux.c
new file mode 100644
index 0000000..b9cea7b
--- /dev/null
+++ b/src/impl_loongarch_linux.c
@@ -0,0 +1,89 @@
+// Copyright 2023 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 "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_LOONGARCH
+#if defined(CPU_FEATURES_OS_LINUX)
+
+#include "cpuinfo_loongarch.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(LOONGARCH_CPUCFG, CPUCFG, "cfg", HWCAP_LOONGARCH_CPUCFG, 0) \
+ LINE(LOONGARCH_LAM, LAM, "lam", HWCAP_LOONGARCH_LAM, 0) \
+ LINE(LOONGARCH_UAL, UAL, "ual", HWCAP_LOONGARCH_UAL, 0) \
+ LINE(LOONGARCH_FPU, FPU, "fpu", HWCAP_LOONGARCH_FPU, 0) \
+ LINE(LOONGARCH_LSX, LSX, "lsx", HWCAP_LOONGARCH_LSX, 0) \
+ LINE(LOONGARCH_LASX, LASX, "lasx", HWCAP_LOONGARCH_LASX, 0) \
+ LINE(LOONGARCH_CRC32, CRC32, "crc32", HWCAP_LOONGARCH_CRC32, 0) \
+ LINE(LOONGARCH_COMPLEX, COMPLEX, "complex", HWCAP_LOONGARCH_COMPLEX, 0) \
+ LINE(LOONGARCH_CRYPTO, CRYPTO, "crypto", HWCAP_LOONGARCH_CRYPTO, 0) \
+ LINE(LOONGARCH_LVZ, LVZ, "lvz", HWCAP_LOONGARCH_LVZ, 0) \
+ LINE(LOONGARCH_LBT_X86, LBT_X86, "lbt_x86", HWCAP_LOONGARCH_LBT_X86, 0) \
+ LINE(LOONGARCH_LBT_ARM, LBT_ARM, "lbt_arm", HWCAP_LOONGARCH_LBT_ARM, 0) \
+ LINE(LOONGARCH_LBT_MIPS, LBT_MIPS, "lbt_mips", HWCAP_LOONGARCH_LBT_MIPS, 0) \
+ LINE(LOONGARCH_PTW, PTW, "ptw", HWCAP_LOONGARCH_PTW, 0)
+#define INTROSPECTION_PREFIX LoongArch
+#define INTROSPECTION_ENUM_PREFIX LOONGARCH
+#include "define_introspection_and_hwcaps.inl"
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "internal/filesystem.h"
+#include "internal/stack_line_reader.h"
+
+static const LoongArchInfo kEmptyLoongArchInfo;
+
+static bool HandleLoongArchLine(const LineResult result, LoongArchInfo* 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 < LOONGARCH_LAST_; ++i) {
+ kSetters[i](&info->features, CpuFeatures_StringView_HasWord(
+ value, kCpuInfoFlags[i], ' '));
+ }
+ }
+ }
+ return !result.eof;
+}
+
+static void FillProcCpuInfoData(LoongArchInfo* const info) {
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ if (!HandleLoongArchLine(StackLineReader_NextLine(&reader), info)) break;
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+}
+
+LoongArchInfo GetLoongArchInfo(void) {
+ LoongArchInfo info = kEmptyLoongArchInfo;
+ FillProcCpuInfoData(&info);
+ return info;
+}
+
+#endif // defined(CPU_FEATURES_OS_LINUX)
+#endif // CPU_FEATURES_ARCH_LOONGARCH
diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl
index 6a34bff..dfff46c 100644
--- a/src/impl_x86__base_implementation.inl
+++ b/src/impl_x86__base_implementation.inl
@@ -166,6 +166,7 @@ typedef struct {
Leaf leaf_80000002; // brand string
Leaf leaf_80000003; // brand string
Leaf leaf_80000004; // brand string
+ Leaf leaf_80000021; // AMD Extended Feature Identification 2
} Leaves;
static Leaves ReadLeaves(void) {
@@ -186,6 +187,7 @@ static Leaves ReadLeaves(void) {
.leaf_80000002 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000002, 0),
.leaf_80000003 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000003, 0),
.leaf_80000004 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000004, 0),
+ .leaf_80000021 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000021, 0),
};
}
@@ -390,6 +392,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
features->fs_rep_cmpsb_scasb = IsBitSet(leaf_7_1.eax, 12);
features->adx = IsBitSet(leaf_7.ebx, 19);
features->lzcnt = IsBitSet(leaf_80000001.ecx, 5);
+ features->lam = IsBitSet(leaf_7_1.eax, 26);
/////////////////////////////////////////////////////////////////////////////
// The following section is devoted to Vector Extensions.
@@ -447,6 +450,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
features->amx_tile = IsBitSet(leaf_7.edx, 24);
features->amx_int8 = IsBitSet(leaf_7.edx, 25);
+ features->amx_fp16 = IsBitSet(leaf_7_1.eax, 21);
}
} else {
// When XCR0 is not available (Atom based or older cpus) we need to defer to
@@ -462,6 +466,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
static void ParseExtraAMDCpuId(const Leaves* leaves, X86Info* info,
OsPreserves os_preserves) {
const Leaf leaf_80000001 = leaves->leaf_80000001;
+ const Leaf leaf_80000021 = leaves->leaf_80000021;
X86Features* const features = &info->features;
@@ -472,6 +477,8 @@ static void ParseExtraAMDCpuId(const Leaves* leaves, X86Info* info,
if (os_preserves.avx_registers) {
features->fma4 = IsBitSet(leaf_80000001.ecx, 16);
}
+
+ features->uai = IsBitSet(leaf_80000021.eax, 7);
}
static const X86Info kEmptyX86Info;
@@ -641,6 +648,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
}
case CPUID(0x06, 0x97):
case CPUID(0x06, 0x9A):
+ case CPUID(0x06, 0xBE):
// https://en.wikichip.org/wiki/intel/microarchitectures/alder_lake
return INTEL_ADL;
case CPUID(0x06, 0xA5):
@@ -811,6 +819,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x17, 0x60):
case CPUID(0x17, 0x68):
case CPUID(0x17, 0x71):
+ case CPUID(0x17, 0x84):
case CPUID(0x17, 0x90):
case CPUID(0x17, 0x98):
case CPUID(0x17, 0xA0):
@@ -827,7 +836,9 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikichip.org/wiki/amd/microarchitectures/zen_3
return AMD_ZEN3;
case CPUID(0x19, 0x10):
+ case CPUID(0x19, 0x11):
case CPUID(0x19, 0x61):
+ case CPUID(0x19, 0x74):
// https://en.wikichip.org/wiki/amd/microarchitectures/zen_4
return AMD_ZEN4;
default:
@@ -1966,6 +1977,7 @@ CacheInfo GetX86CacheInfo(void) {
LINE(X86_AMX_BF16, amx_bf16, , , ) \
LINE(X86_AMX_TILE, amx_tile, , , ) \
LINE(X86_AMX_INT8, amx_int8, , , ) \
+ LINE(X86_AMX_FP16, amx_fp16, , , ) \
LINE(X86_PCLMULQDQ, pclmulqdq, , , ) \
LINE(X86_SMX, smx, , , ) \
LINE(X86_SGX, sgx, , , ) \
@@ -1984,7 +1996,9 @@ CacheInfo GetX86CacheInfo(void) {
LINE(X86_FS_REP_MOV, fs_rep_mov, , , ) \
LINE(X86_FZ_REP_MOVSB, fz_rep_movsb, , , ) \
LINE(X86_FS_REP_STOSB, fs_rep_stosb, , , ) \
- LINE(X86_FS_REP_CMPSB_SCASB, fs_rep_cmpsb_scasb, , , )
+ LINE(X86_FS_REP_CMPSB_SCASB, fs_rep_cmpsb_scasb, , , ) \
+ LINE(X86_LAM, lam, , , ) \
+ LINE(X86_UAI, uai, , , )
#define INTROSPECTION_PREFIX X86
#define INTROSPECTION_ENUM_PREFIX X86
#include "define_introspection.inl"
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index 8226d85..83cd387 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -39,6 +39,8 @@
#include "cpuinfo_s390x.h"
#elif defined(CPU_FEATURES_ARCH_RISCV)
#include "cpuinfo_riscv.h"
+#elif defined(CPU_FEATURES_ARCH_LOONGARCH)
+#include "cpuinfo_loongarch.h"
#endif
// Design principles
@@ -215,6 +217,9 @@ DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatu
#elif defined(CPU_FEATURES_ARCH_RISCV)
DEFINE_ADD_FLAGS(GetRiscvFeaturesEnumValue, GetRiscvFeaturesEnumName, RiscvFeatures,
RISCV_LAST_)
+#elif defined(CPU_FEATURES_ARCH_LOONGARCH)
+DEFINE_ADD_FLAGS(GetLoongArchFeaturesEnumValue, GetLoongArchFeaturesEnumName, LoongArchFeatures,
+ LOONGARCH_LAST_)
#endif
// Prints a json string with characters escaping.
@@ -432,6 +437,10 @@ static Node* CreateTree(void) {
AddMapEntry(root, "vendor", CreateString(info.vendor));
AddMapEntry(root, "microarchitecture", CreateString(info.uarch));
AddFlags(root, &info.features);
+#elif defined(CPU_FEATURES_ARCH_LOONGARCH)
+ const LoongArchInfo info = GetLoongArchInfo();
+ AddMapEntry(root, "arch", CreateString("loongarch"));
+ AddFlags(root, &info.features);
#endif
return root;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f627d74..f21ff98 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -74,8 +74,15 @@ if(PROCESSOR_IS_AARCH64)
add_executable(cpuinfo_aarch64_test
cpuinfo_aarch64_test.cc
../src/impl_aarch64_linux_or_android.c
- ../src/impl_aarch64_windows.c)
- target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64)
+ ../src/impl_aarch64_windows.c
+ ../src/impl_aarch64_macos_or_iphone.c
+ )
+ if(APPLE)
+ target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_SYSCTL_AARCH64)
+ target_compile_definitions(cpuinfo_aarch64_test PRIVATE HAVE_SYSCTLBYNAME)
+ else()
+ target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64)
+ endif()
target_link_libraries(cpuinfo_aarch64_test all_libraries)
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
endif()
@@ -107,3 +114,11 @@ if(PROCESSOR_IS_RISCV)
target_link_libraries(cpuinfo_riscv_test all_libraries)
add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test)
endif()
+##------------------------------------------------------------------------------
+## cpuinfo_loongarch_test
+if(PROCESSOR_IS_LOONGARCH)
+ add_executable(cpuinfo_loongarch_test cpuinfo_loongarch_test.cc ../src/impl_loongarch_linux.c)
+ target_link_libraries(cpuinfo_loongarch_test all_libraries)
+ add_test(NAME cpuinfo_loongarch_test COMMAND cpuinfo_loongarch_test)
+endif()
+
diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc
index ef9abae..6aefa6b 100644
--- a/test/cpuinfo_aarch64_test.cc
+++ b/test/cpuinfo_aarch64_test.cc
@@ -25,8 +25,35 @@
namespace cpu_features {
class FakeCpuAarch64 {
+#if defined(CPU_FEATURES_OS_LINUX)
+ // No particular implementation for Linux as we use /proc/cpuinfo
+#elif defined(CPU_FEATURES_OS_MACOS)
+ std::set<std::string> darwin_sysctlbyname_;
+ std::map<std::string, int> darwin_sysctlbynamevalue_;
+
+ public:
+ bool GetDarwinSysCtlByName(std::string name) const {
+ return darwin_sysctlbyname_.count(name);
+ }
+
+ int GetDarwinSysCtlByNameValue(std::string name) const {
+ const auto iter = darwin_sysctlbynamevalue_.find(name);
+ if (iter != darwin_sysctlbynamevalue_.end()) return iter->second;
+ return 0;
+ }
+
+ void SetDarwinSysCtlByName(std::string name) {
+ darwin_sysctlbyname_.insert(name);
+ }
+
+ void SetDarwinSysCtlByNameValue(std::string name, int value) {
+ darwin_sysctlbynamevalue_[name] = value;
+ }
+#elif defined(CPU_FEATURES_OS_WINDOWS)
+ std::set<DWORD> windows_isprocessorfeaturepresent_;
+ WORD processor_revision_{};
+
public:
-#if defined(CPU_FEATURES_OS_WINDOWS)
bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
return windows_isprocessorfeaturepresent_.count(dwProcessorFeature);
}
@@ -42,11 +69,7 @@ class FakeCpuAarch64 {
void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) {
processor_revision_ = wProcessorRevision;
}
-
- private:
- std::set<DWORD> windows_isprocessorfeaturepresent_;
- WORD processor_revision_{};
-#endif // CPU_FEATURES_OS_WINDOWS
+#endif
};
static FakeCpuAarch64* g_fake_cpu_instance = nullptr;
@@ -56,7 +79,18 @@ static FakeCpuAarch64& cpu() {
return *g_fake_cpu_instance;
}
-#if defined(CPU_FEATURES_OS_WINDOWS)
+// Define OS dependent mock functions
+#if defined(CPU_FEATURES_OS_LINUX)
+// No particular functions to implement for Linux as we use /proc/cpuinfo
+#elif defined(CPU_FEATURES_OS_MACOS)
+extern "C" bool GetDarwinSysCtlByName(const char* name) {
+ return cpu().GetDarwinSysCtlByName(name);
+}
+
+extern "C" int GetDarwinSysCtlByNameValue(const char* name) {
+ return cpu().GetDarwinSysCtlByNameValue(name);
+}
+#elif defined(CPU_FEATURES_OS_WINDOWS)
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature);
}
@@ -64,7 +98,7 @@ extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() {
return cpu().GetWindowsNativeSystemInfoProcessorRevision();
}
-#endif // CPU_FEATURES_OS_WINDOWS
+#endif
namespace {
@@ -80,7 +114,7 @@ class CpuidAarch64Test : public ::testing::Test {
}
};
-TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) {
+TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) {
const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(AARCH64_FP);
@@ -93,10 +127,9 @@ TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) {
}
}
+// OS dependent tests
#if defined(CPU_FEATURES_OS_LINUX)
-void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
-
-TEST(CpuinfoAarch64Test, FromHardwareCap) {
+TEST_F(CpuidAarch64Test, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
@@ -135,7 +168,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) {
EXPECT_FALSE(info.features.pacg);
}
-TEST(CpuinfoAarch64Test, FromHardwareCap2) {
+TEST_F(CpuidAarch64Test, FromHardwareCap2) {
ResetHwcaps();
SetHardwareCapabilities(AARCH64_HWCAP_FP,
AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
@@ -164,7 +197,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap2) {
EXPECT_FALSE(info.features.rng);
}
-TEST(CpuinfoAarch64Test, ARMCortexA53) {
+TEST_F(CpuidAarch64Test, ARMCortexA53) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
@@ -244,10 +277,90 @@ CPU revision : 3)");
EXPECT_FALSE(info.features.ecv);
EXPECT_FALSE(info.features.afp);
EXPECT_FALSE(info.features.rpres);
+ EXPECT_FALSE(info.features.mte3);
+ EXPECT_FALSE(info.features.sme);
+ EXPECT_FALSE(info.features.smei16i64);
+ EXPECT_FALSE(info.features.smef64f64);
+ EXPECT_FALSE(info.features.smei8i32);
+ EXPECT_FALSE(info.features.smef16f32);
+ EXPECT_FALSE(info.features.smeb16f32);
+ EXPECT_FALSE(info.features.smef32f32);
+ EXPECT_FALSE(info.features.smefa64);
+ EXPECT_FALSE(info.features.wfxt);
+ EXPECT_FALSE(info.features.ebf16);
+ EXPECT_FALSE(info.features.sveebf16);
+ EXPECT_FALSE(info.features.cssc);
+ EXPECT_FALSE(info.features.rprfm);
+ EXPECT_FALSE(info.features.sve2p1);
+ EXPECT_FALSE(info.features.sme2);
+ EXPECT_FALSE(info.features.sme2p1);
+ EXPECT_FALSE(info.features.smei16i32);
+ EXPECT_FALSE(info.features.smebi32i32);
+ EXPECT_FALSE(info.features.smeb16b16);
+ EXPECT_FALSE(info.features.smef16f16);
}
-#endif // CPU_FEATURES_OS_LINUX
+#elif defined(CPU_FEATURES_OS_MACOS)
+TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName) {
+ cpu().SetDarwinSysCtlByName("hw.optional.floatingpoint");
+ cpu().SetDarwinSysCtlByName("hw.optional.neon");
+ cpu().SetDarwinSysCtlByName("hw.optional.AdvSIMD_HPFPCvt");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FP16");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE");
+ cpu().SetDarwinSysCtlByName("hw.optional.armv8_crc32");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FHM");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA512");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA3");
+ cpu().SetDarwinSysCtlByName("hw.optional.amx_version");
+ cpu().SetDarwinSysCtlByName("hw.optional.ucnormal_mem");
+ cpu().SetDarwinSysCtlByName("hw.optional.arm64");
-#if defined(CPU_FEATURES_OS_WINDOWS)
+ cpu().SetDarwinSysCtlByNameValue("hw.cputype", 16777228);
+ cpu().SetDarwinSysCtlByNameValue("hw.cpusubtype", 2);
+ cpu().SetDarwinSysCtlByNameValue("hw.cpu64bit", 1);
+ cpu().SetDarwinSysCtlByNameValue("hw.cpufamily", 458787763);
+ cpu().SetDarwinSysCtlByNameValue("hw.cpusubfamily", 2);
+
+ const auto info = GetAarch64Info();
+
+ EXPECT_EQ(info.implementer, 0x100000C);
+ EXPECT_EQ(info.variant, 2);
+ EXPECT_EQ(info.part, 0x1B588BB3);
+ EXPECT_EQ(info.revision, 2);
+
+ EXPECT_TRUE(info.features.fp);
+ EXPECT_FALSE(info.features.asimd);
+ 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_TRUE(info.features.crc32);
+ EXPECT_TRUE(info.features.atomics);
+ EXPECT_TRUE(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_TRUE(info.features.sha3);
+ EXPECT_FALSE(info.features.sm3);
+ EXPECT_FALSE(info.features.sm4);
+ EXPECT_FALSE(info.features.asimddp);
+ EXPECT_TRUE(info.features.sha512);
+ EXPECT_FALSE(info.features.sve);
+ EXPECT_TRUE(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);
+}
+#elif defined(CPU_FEATURES_OS_WINDOWS)
TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03);
cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
@@ -271,6 +384,5 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
EXPECT_FALSE(info.features.lrcpc);
}
#endif // CPU_FEATURES_OS_WINDOWS
-
} // namespace
} // namespace cpu_features
diff --git a/test/cpuinfo_loongarch_test.cc b/test/cpuinfo_loongarch_test.cc
new file mode 100644
index 0000000..14f544f
--- /dev/null
+++ b/test/cpuinfo_loongarch_test.cc
@@ -0,0 +1,179 @@
+// Copyright 2022 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_loongarch.h"
+
+#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
+
+namespace cpu_features {
+namespace {
+
+TEST(CpuinfoLoongArchvTest, UnknownFromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+system type : generic-loongson-machine
+
+processor : 0
+package : 0
+core : 0
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000-HV
+CPU Revision : 0x11
+FPU Revision : 0x00
+CPU MHz : 2500.00
+BogoMIPS : 5000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips
+Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8
+
+processor : 1
+package : 0
+core : 1
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000-HV
+CPU Revision : 0x11
+FPU Revision : 0x00
+CPU MHz : 2500.00
+BogoMIPS : 5000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips
+Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8
+
+processor : 2
+package : 0
+core : 2
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000-HV
+CPU Revision : 0x11
+FPU Revision : 0x00
+CPU MHz : 2500.00
+BogoMIPS : 5000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips
+Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8
+
+processor : 3
+package : 0
+core : 3
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000-HV
+CPU Revision : 0x11
+FPU Revision : 0x00
+CPU MHz : 2500.00
+BogoMIPS : 5000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips
+Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8)");
+ const auto info = GetLoongArchInfo();
+ EXPECT_FALSE(info.features.CPUCFG);
+ EXPECT_TRUE(info.features.LAM);
+ EXPECT_TRUE(info.features.UAL);
+ EXPECT_TRUE(info.features.FPU);
+ EXPECT_TRUE(info.features.LSX);
+ EXPECT_TRUE(info.features.LASX);
+ EXPECT_TRUE(info.features.CRC32);
+ EXPECT_TRUE(info.features.COMPLEX);
+ EXPECT_TRUE(info.features.CRYPTO);
+ EXPECT_TRUE(info.features.LVZ);
+ EXPECT_TRUE(info.features.LBT_X86);
+ EXPECT_TRUE(info.features.LBT_ARM);
+ EXPECT_TRUE(info.features.LBT_MIPS);
+}
+
+TEST(CpuinfoLoongArchvTest, QemuCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+system type : generic-loongson-machine
+
+processor : 0
+package : 0
+core : 0
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000
+CPU Revision : 0x10
+FPU Revision : 0x01
+CPU MHz : 2000.00
+BogoMIPS : 4000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu crc32
+Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0
+
+processor : 1
+package : 0
+core : 1
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000
+CPU Revision : 0x10
+FPU Revision : 0x01
+CPU MHz : 2000.00
+BogoMIPS : 4000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu crc32
+Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0
+
+processor : 2
+package : 0
+core : 2
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000
+CPU Revision : 0x10
+FPU Revision : 0x01
+CPU MHz : 2000.00
+BogoMIPS : 4000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu crc32
+Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0
+
+processor : 3
+package : 0
+core : 3
+CPU Family : Loongson-64bit
+Model Name : Loongson-3A5000
+CPU Revision : 0x10
+FPU Revision : 0x01
+CPU MHz : 2000.00
+BogoMIPS : 4000.00
+TLB Entries : 2112
+Address Sizes : 48 bits physical, 48 bits virtual
+ISA : loongarch32 loongarch64
+Features : cpucfg lam ual fpu crc32
+Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0)");
+ const auto info = GetLoongArchInfo();
+ EXPECT_FALSE(info.features.CPUCFG);
+ EXPECT_TRUE(info.features.LAM);
+ EXPECT_TRUE(info.features.UAL);
+ EXPECT_TRUE(info.features.FPU);
+ EXPECT_TRUE(info.features.CRC32);
+}
+
+} // namespace
+} // namespace cpu_features
diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc
index de271cc..328aa5c 100644
--- a/test/cpuinfo_x86_test.cc
+++ b/test/cpuinfo_x86_test.cc
@@ -184,6 +184,8 @@ TEST_F(CpuidX86Test, SandyBridge) {
EXPECT_FALSE(features.movbe);
EXPECT_FALSE(features.rdrnd);
EXPECT_FALSE(features.adx);
+ EXPECT_FALSE(features.lam);
+ EXPECT_FALSE(features.uai);
}
const int UNDEF = -1;
@@ -770,6 +772,20 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) {
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2);
}
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0880F40_K17_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K17_ZEN2_4800S) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00880F40, 0x00100800, 0x7ED8320B, 0x178BFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x17);
+ EXPECT_EQ(info.model, 0x84);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2);
+}
+
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt
TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) {
cpu().SetLeaves({
@@ -894,6 +910,7 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN4_RAPHAEL) {
{{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2035206E, 0x30303637}},
{{0x80000003, 0}, Leaf{0x2D362058, 0x65726F43, 0x6F725020, 0x73736563}},
{{0x80000004, 0}, Leaf{0x2020726F, 0x20202020, 0x20202020, 0x00202020}},
+ {{0x80000021, 0}, Leaf{0x00062FCF, 0x0000015C, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
@@ -902,9 +919,25 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN4_RAPHAEL) {
EXPECT_EQ(info.model, 0x61);
EXPECT_STREQ(info.brand_string,
"AMD Ryzen 5 7600X 6-Core Processor ");
+ EXPECT_TRUE(info.features.uai);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN4);
}
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A70F41_K19_Phoenix_03_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K19_ZEN4_PHOENIX) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00A70F41, 0x00100800, 0x7EF8320B, 0x178BFBFF}},
+ {{0x80000000, 0}, Leaf{0x80000028, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00A70F41, 0x50000000, 0x75C237FF, 0x2FD3FBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x19);
+ EXPECT_EQ(info.model, 0x74);
+}
+
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F11_Hygon_01_CPUID.txt
TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_OCTAL_CORE_C86_3250) {
cpu().SetLeaves({
@@ -940,6 +973,20 @@ TEST_F(CpuidX86Test, AMD_ZEN2_MENDOCINO) {
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2);
}
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A10F11_K19_Genoa_02_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K19_ZEN4_GENOA) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00A10F11, 0x00200800, 0x7EFA320B, 0x178BFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_EQ(info.model, 0x11);
+ EXPECT_EQ(info.family, 0x19);
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN4);
+}
+
// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00906A4_AlderLakeP_00_CPUID.txt
TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_AVX_VNNI) {
cpu().SetOsBackupsExtendedRegisters(true);
@@ -1689,6 +1736,20 @@ TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_S) {
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL);
}
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06E0_AlderLakeN_03_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_N) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000B06E0, 0x00800800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0xBE);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL);
+}
+
// https://github.com/google/cpu_features/issues/200
// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt
#if defined(CPU_FEATURES_OS_WINDOWS)