aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Levillain <rpl@google.com>2023-04-27 16:34:13 +0100
committerRoland Levillain <rpl@google.com>2023-04-27 17:27:29 +0100
commit50b79af61d87d88428cba29b436e7109b95f35db (patch)
tree274e1e79e270c332b8d055d5e25b0b0e33c78365
parent6dd8c6baeeff0983891ecab6b47a9adc8b736ee7 (diff)
parent936b9ab5515dead115606559502e3864958f7f6e (diff)
downloadcpu_features-50b79af61d87d88428cba29b436e7109b95f35db.tar.gz
Merge v0.8.0 into master.
Test: Run `atest -a --test-mapping external/cpu_features:all` (on x86-64 and Arm64 devices) Change-Id: Ia6cbc61e844a10e3dc76d3ee92bf214da89651a2
-rw-r--r--.dockerignore8
-rw-r--r--.github/workflows/aarch64_linux_cmake.yml (renamed from .github/workflows/aarch64_linux.yml)10
-rw-r--r--.github/workflows/amd64_freebsd_cmake.yml (renamed from .github/workflows/amd64_freebsd.yml)6
-rw-r--r--.github/workflows/amd64_linux.yml31
-rw-r--r--.github/workflows/amd64_linux_bazel.yml26
-rw-r--r--.github/workflows/amd64_linux_cmake.yml31
-rw-r--r--.github/workflows/amd64_macos_cmake.yml (renamed from .github/workflows/amd64_macos.yml)2
-rw-r--r--.github/workflows/amd64_windows_cmake.yml (renamed from .github/workflows/amd64_windows.yml)2
-rw-r--r--.github/workflows/arm_linux_cmake.yml (renamed from .github/workflows/arm_linux.yml)8
-rw-r--r--.github/workflows/mips_linux_cmake.yml (renamed from .github/workflows/mips_linux.yml)8
-rw-r--r--.github/workflows/power_linux_cmake.yml29
-rw-r--r--.github/workflows/riscv_linux_cmake.yml28
-rw-r--r--.github/workflows/s390x_linux_cmake.yml27
-rw-r--r--.grenrc.yml21
-rw-r--r--BUILD.bazel41
-rw-r--r--CMakeLists.txt18
-rw-r--r--METADATA8
-rw-r--r--README.md108
-rw-r--r--WORKSPACE18
-rw-r--r--bazel/ci/README.md5
-rw-r--r--ci/README.md66
-rw-r--r--cmake/README.md2
-rw-r--r--cmake/ci/Makefile (renamed from ci/Makefile)18
-rw-r--r--cmake/ci/README.md40
-rw-r--r--cmake/ci/doc/docker.dot (renamed from ci/doc/docker.dot)0
-rw-r--r--cmake/ci/doc/docker.svg (renamed from ci/doc/docker.svg)0
-rwxr-xr-xcmake/ci/doc/generate_image.sh (renamed from ci/doc/generate_image.sh)0
-rw-r--r--cmake/ci/docker/amd64/Dockerfile (renamed from ci/docker/amd64/Dockerfile)2
-rw-r--r--cmake/ci/docker/toolchain/Dockerfile (renamed from ci/docker/toolchain/Dockerfile)0
-rw-r--r--cmake/ci/sample/CMakeLists.txt (renamed from ci/sample/CMakeLists.txt)0
-rw-r--r--cmake/ci/sample/main.cpp (renamed from ci/sample/main.cpp)0
-rw-r--r--cmake/ci/vagrant/freebsd/Vagrantfile (renamed from ci/vagrant/freebsd/Vagrantfile)15
-rw-r--r--include/cpu_features_macros.h137
-rw-r--r--include/cpuinfo_aarch64.h109
-rw-r--r--include/cpuinfo_mips.h24
-rw-r--r--include/cpuinfo_riscv.h72
-rw-r--r--include/cpuinfo_s390x.h108
-rw-r--r--include/cpuinfo_x86.h127
-rw-r--r--include/internal/hwcaps.h50
-rw-r--r--include/internal/windows_utils.h70
-rw-r--r--scripts/generate_badges.d165
-rwxr-xr-xscripts/make_release.sh5
-rwxr-xr-xscripts/run_integration.sh169
-rw-r--r--src/impl_aarch64_linux_or_android.c5
-rw-r--r--src/impl_aarch64_windows.c138
-rw-r--r--src/impl_mips_linux_or_android.c13
-rw-r--r--src/impl_ppc_linux.c1
-rw-r--r--src/impl_riscv_linux.c111
-rw-r--r--src/impl_s390x_linux.c120
-rw-r--r--src/impl_x86__base_implementation.inl293
-rw-r--r--src/impl_x86_windows.c20
-rw-r--r--src/utils/list_cpu_features.c40
-rw-r--r--test/CMakeLists.txt20
-rw-r--r--test/cpuinfo_aarch64_test.cc102
-rw-r--r--test/cpuinfo_arm_test.cc12
-rw-r--r--test/cpuinfo_mips_test.cc50
-rw-r--r--test/cpuinfo_ppc_test.cc12
-rw-r--r--test/cpuinfo_riscv_test.cc180
-rw-r--r--test/cpuinfo_s390x_test.cc82
-rw-r--r--test/cpuinfo_x86_test.cc820
60 files changed, 3182 insertions, 451 deletions
diff --git a/.dockerignore b/.dockerignore
index 716b782..65950ea 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,8 +1,8 @@
# Project Files unneeded by docker
-ci/Makefile
-ci/docker
-ci/doc
-ci/cache
+cmake/ci/Makefile
+cmake/ci/docker
+cmake/ci/doc
+cmake/ci/cache
.git
.gitignore
.github
diff --git a/.github/workflows/aarch64_linux.yml b/.github/workflows/aarch64_linux_cmake.yml
index 2de7289..3e2d53c 100644
--- a/.github/workflows/aarch64_linux.yml
+++ b/.github/workflows/aarch64_linux_cmake.yml
@@ -1,4 +1,4 @@
-name: aarch64 Linux
+name: AArch64 Linux CMake
on:
push:
@@ -9,11 +9,13 @@ on:
jobs:
# Building using the github runner environement directly.
- aarch64:
+ make:
runs-on: ubuntu-latest
strategy:
matrix:
targets: [
+ [aarch64],
+ [aarch64be],
[aarch64-linux-gnu],
[aarch64_be-linux-gnu]
]
@@ -23,6 +25,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build
- run: make --directory=ci ${TARGET}_build
+ run: make --directory=cmake/ci ${TARGET}_build
- name: Test
- run: make --directory=ci ${TARGET}_test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.github/workflows/amd64_freebsd.yml b/.github/workflows/amd64_freebsd_cmake.yml
index eeab380..8bad4f8 100644
--- a/.github/workflows/amd64_freebsd.yml
+++ b/.github/workflows/amd64_freebsd_cmake.yml
@@ -1,4 +1,4 @@
-name: amd64 FreeBSD
+name: amd64 FreeBSD CMake
on:
push:
@@ -10,7 +10,7 @@ on:
jobs:
# Only MacOS hosted runner provides virtualisation with vagrant/virtualbox installed.
# see: https://github.com/actions/virtual-environments/tree/main/images/macos
- freebsd:
+ make:
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
@@ -19,4 +19,4 @@ jobs:
- name: VirtualBox version
run: virtualbox -h
- name: Build
- run: cd ci/vagrant/freebsd && vagrant up
+ run: cd cmake/ci/vagrant/freebsd && vagrant up
diff --git a/.github/workflows/amd64_linux.yml b/.github/workflows/amd64_linux.yml
deleted file mode 100644
index 21f4f90..0000000
--- a/.github/workflows/amd64_linux.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: amd64 Linux
-
-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.
- make:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Env
- run: make --directory=ci amd64_env
- - name: Devel
- run: make --directory=ci amd64_devel
- - name: Build
- run: make --directory=ci amd64_build
- - name: Test
- run: make --directory=ci amd64_test
- - name: Install Env
- run: make --directory=ci amd64_install_env
- - name: Install Devel
- run: make --directory=ci amd64_install_devel
- - name: Install Build
- run: make --directory=ci amd64_install_build
- - name: Install Test
- run: make --directory=ci amd64_install_test
diff --git a/.github/workflows/amd64_linux_bazel.yml b/.github/workflows/amd64_linux_bazel.yml
new file mode 100644
index 0000000..599faf5
--- /dev/null
+++ b/.github/workflows/amd64_linux_bazel.yml
@@ -0,0 +1,26 @@
+name: amd64 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@v2
+ - name: Install Bazel
+ 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
+ - name: Test
+ run: bazel test -s --verbose_failures //...
diff --git a/.github/workflows/amd64_linux_cmake.yml b/.github/workflows/amd64_linux_cmake.yml
new file mode 100644
index 0000000..90ccc80
--- /dev/null
+++ b/.github/workflows/amd64_linux_cmake.yml
@@ -0,0 +1,31 @@
+name: amd64 Linux CMake
+
+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.
+ make:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Env
+ run: make --directory=cmake/ci amd64_env
+ - name: Devel
+ run: make --directory=cmake/ci amd64_devel
+ - name: Build
+ run: make --directory=cmake/ci amd64_build
+ - name: Test
+ run: make --directory=cmake/ci amd64_test
+ - name: Install Env
+ run: make --directory=cmake/ci amd64_install_env
+ - name: Install Devel
+ run: make --directory=cmake/ci amd64_install_devel
+ - name: Install Build
+ run: make --directory=cmake/ci amd64_install_build
+ - name: Install Test
+ run: make --directory=cmake/ci amd64_install_test
diff --git a/.github/workflows/amd64_macos.yml b/.github/workflows/amd64_macos_cmake.yml
index 19ec18c..3756500 100644
--- a/.github/workflows/amd64_macos.yml
+++ b/.github/workflows/amd64_macos_cmake.yml
@@ -1,4 +1,4 @@
-name: amd64 macOS
+name: amd64 MacOS CMake
on:
push:
diff --git a/.github/workflows/amd64_windows.yml b/.github/workflows/amd64_windows_cmake.yml
index 7ff1ac0..7118533 100644
--- a/.github/workflows/amd64_windows.yml
+++ b/.github/workflows/amd64_windows_cmake.yml
@@ -1,4 +1,4 @@
-name: amd64 Windows
+name: amd64 Windows CMake
on:
push:
diff --git a/.github/workflows/arm_linux.yml b/.github/workflows/arm_linux_cmake.yml
index 2272188..87bb6bb 100644
--- a/.github/workflows/arm_linux.yml
+++ b/.github/workflows/arm_linux_cmake.yml
@@ -1,4 +1,4 @@
-name: arm Linux
+name: ARM Linux CMake
on:
push:
@@ -9,7 +9,7 @@ on:
jobs:
# Building using the github runner environement directly.
- arm:
+ make:
runs-on: ubuntu-latest
strategy:
matrix:
@@ -26,6 +26,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build
- run: make --directory=ci ${TARGET}_build
+ run: make --directory=cmake/ci ${TARGET}_build
- name: Test
- run: make --directory=ci ${TARGET}_test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.github/workflows/mips_linux.yml b/.github/workflows/mips_linux_cmake.yml
index 571de3a..9ce7901 100644
--- a/.github/workflows/mips_linux.yml
+++ b/.github/workflows/mips_linux_cmake.yml
@@ -1,4 +1,4 @@
-name: mips Linux
+name: MIPS Linux CMake
on:
push:
@@ -9,7 +9,7 @@ on:
jobs:
# Building using the github runner environement directly.
- mips:
+ make:
runs-on: ubuntu-latest
strategy:
matrix:
@@ -25,6 +25,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build
- run: make --directory=ci ${TARGET}_build
+ run: make --directory=cmake/ci ${TARGET}_build
- name: Test
- run: make --directory=ci ${TARGET}_test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.github/workflows/power_linux_cmake.yml b/.github/workflows/power_linux_cmake.yml
new file mode 100644
index 0000000..bc890e2
--- /dev/null
+++ b/.github/workflows/power_linux_cmake.yml
@@ -0,0 +1,29 @@
+name: POWER Linux CMake
+
+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.
+ make:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ targets: [
+ [ppc],
+ [ppc64],
+ [ppc64le],
+ ]
+ fail-fast: false
+ env:
+ TARGET: ${{ matrix.targets[0] }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Build
+ run: make --directory=cmake/ci ${TARGET}_build
+ - name: Test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.github/workflows/riscv_linux_cmake.yml b/.github/workflows/riscv_linux_cmake.yml
new file mode 100644
index 0000000..ef7586a
--- /dev/null
+++ b/.github/workflows/riscv_linux_cmake.yml
@@ -0,0 +1,28 @@
+name: RISCV Linux CMake
+
+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.
+ make:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ targets: [
+ [riscv32],
+ [riscv64],
+ ]
+ fail-fast: false
+ env:
+ TARGET: ${{ matrix.targets[0] }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Build
+ run: make --directory=cmake/ci ${TARGET}_build
+ - name: Test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.github/workflows/s390x_linux_cmake.yml b/.github/workflows/s390x_linux_cmake.yml
new file mode 100644
index 0000000..5be96a1
--- /dev/null
+++ b/.github/workflows/s390x_linux_cmake.yml
@@ -0,0 +1,27 @@
+name: s390x Linux CMake
+
+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.
+ make:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ targets: [
+ [s390x],
+ ]
+ fail-fast: false
+ env:
+ TARGET: ${{ matrix.targets[0] }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Build
+ run: make --directory=cmake/ci ${TARGET}_build
+ - name: Test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/.grenrc.yml b/.grenrc.yml
new file mode 100644
index 0000000..77dd755
--- /dev/null
+++ b/.grenrc.yml
@@ -0,0 +1,21 @@
+---
+ dataSource: "prs"
+ ignoreLabels:
+ - "Apple M1"
+ - "duplicate"
+ - "help wanted"
+ - "invalid"
+ - "question"
+ - "wontfix"
+ onlyMilestones: false
+ groupBy:
+ "API Change":
+ - "API Change"
+ "New features / Enhancements":
+ - "enhancement"
+ - "internal"
+ "Bug Fixes":
+ - "bug"
+ "Misc":
+ - "misc"
+ changelogFilename: "CHANGELOG.md"
diff --git a/BUILD.bazel b/BUILD.bazel
index 1b62d66..116ef6a 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -28,24 +28,24 @@ C99_FLAGS = [
cc_library(
name = "cpu_features_macros",
- hdrs = ["include/cpu_features_macros.h"],
copts = C99_FLAGS,
includes = INCLUDES,
+ textual_hdrs = ["include/cpu_features_macros.h"],
)
cc_library(
name = "cpu_features_cache_info",
- hdrs = ["include/cpu_features_cache_info.h"],
copts = C99_FLAGS,
includes = INCLUDES,
+ textual_hdrs = ["include/cpu_features_cache_info.h"],
deps = [":cpu_features_macros"],
)
cc_library(
name = "bit_utils",
- hdrs = ["include/internal/bit_utils.h"],
copts = C99_FLAGS,
includes = INCLUDES,
+ textual_hdrs = ["include/internal/bit_utils.h"],
deps = [":cpu_features_macros"],
)
@@ -74,9 +74,9 @@ cc_library(
srcs = [
"src/string_view.c",
],
- hdrs = ["include/internal/string_view.h"],
copts = C99_FLAGS,
includes = INCLUDES,
+ textual_hdrs = ["include/internal/string_view.h"],
deps = [
":cpu_features_macros",
":memory_utils",
@@ -96,9 +96,9 @@ cc_test(
cc_library(
name = "filesystem",
srcs = ["src/filesystem.c"],
- hdrs = ["include/internal/filesystem.h"],
copts = C99_FLAGS,
includes = INCLUDES,
+ textual_hdrs = ["include/internal/filesystem.h"],
deps = [":cpu_features_macros"],
)
@@ -113,8 +113,8 @@ cc_library(
"include/internal/filesystem.h",
"test/filesystem_for_testing.h",
],
- includes = INCLUDES,
defines = ["CPU_FEATURES_MOCK_FILESYSTEM"],
+ includes = INCLUDES,
deps = [
":cpu_features_macros",
],
@@ -123,10 +123,10 @@ cc_library(
cc_library(
name = "stack_line_reader",
srcs = ["src/stack_line_reader.c"],
- hdrs = ["include/internal/stack_line_reader.h"],
copts = C99_FLAGS,
- includes = INCLUDES,
defines = ["STACK_LINE_READER_BUFFER_SIZE=1024"],
+ includes = INCLUDES,
+ textual_hdrs = ["include/internal/stack_line_reader.h"],
deps = [
":cpu_features_macros",
":filesystem",
@@ -141,8 +141,8 @@ cc_test(
"src/stack_line_reader.c",
"test/stack_line_reader_test.cc",
],
- includes = INCLUDES,
defines = ["STACK_LINE_READER_BUFFER_SIZE=16"],
+ includes = INCLUDES,
deps = [
":cpu_features_macros",
":filesystem_for_testing",
@@ -157,8 +157,8 @@ cc_library(
srcs = ["src/stack_line_reader.c"],
hdrs = ["include/internal/stack_line_reader.h"],
copts = C99_FLAGS,
- includes = INCLUDES,
defines = ["STACK_LINE_READER_BUFFER_SIZE=1024"],
+ includes = INCLUDES,
deps = [
":cpu_features_macros",
":filesystem_for_testing",
@@ -169,10 +169,10 @@ cc_library(
cc_library(
name = "hwcaps",
srcs = ["src/hwcaps.c"],
- hdrs = ["include/internal/hwcaps.h"],
copts = C99_FLAGS,
- includes = INCLUDES,
defines = ["HAVE_STRONG_GETAUXVAL"],
+ includes = INCLUDES,
+ textual_hdrs = ["include/internal/hwcaps.h"],
deps = [
":cpu_features_macros",
":filesystem",
@@ -191,11 +191,11 @@ cc_library(
"include/internal/hwcaps.h",
"test/hwcaps_for_testing.h",
],
- includes = INCLUDES,
defines = [
"CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL",
"CPU_FEATURES_TEST",
],
+ includes = INCLUDES,
deps = [
":cpu_features_macros",
":filesystem_for_testing",
@@ -217,21 +217,19 @@ cc_library(
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
}),
- hdrs = selects.with_or({
+ copts = C99_FLAGS,
+ includes = INCLUDES,
+ textual_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",
],
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
- }),
- copts = C99_FLAGS,
- includes = INCLUDES,
- textual_hdrs = selects.with_or({
- PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
- "//conditions:default": [],
}) + [
"src/define_introspection.inl",
"src/define_introspection_and_hwcaps.inl",
@@ -267,6 +265,7 @@ cc_library(
PLATFORM_CPU_X86_64: [
"include/cpuinfo_x86.h",
"include/internal/cpuid_x86.h",
+ "include/internal/windows_utils.h",
],
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
@@ -274,11 +273,11 @@ cc_library(
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
}),
copts = C99_FLAGS,
- includes = INCLUDES,
defines = selects.with_or({
PLATFORM_CPU_X86_64: ["CPU_FEATURES_MOCK_CPUID_X86"],
"//conditions:default": [],
}),
+ includes = INCLUDES,
textual_hdrs = selects.with_or({
PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
"//conditions:default": [],
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81451d4..bcc9bb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
-project(CpuFeatures VERSION 0.7.0 LANGUAGES C)
+project(CpuFeatures VERSION 0.8.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
@@ -49,6 +49,8 @@ set(PROCESSOR_IS_ARM FALSE)
set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
+set(PROCESSOR_IS_S390X FALSE)
+set(PROCESSOR_IS_RISCV FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
@@ -60,6 +62,10 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
set(PROCESSOR_IS_X86 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
+ set(PROCESSOR_IS_S390X TRUE)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
+ set(PROCESSOR_IS_RISCV TRUE)
endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
@@ -73,11 +79,17 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
elseif(PROCESSOR_IS_AARCH64)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
+ list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
elseif(PROCESSOR_IS_X86)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
+ list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
elseif(PROCESSOR_IS_POWER)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
+ elseif(PROCESSOR_IS_S390X)
+ 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)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
@@ -168,9 +180,9 @@ if(BUILD_TESTING)
# found.
enable_language(CXX)
- set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
+ set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std14 instead of -gnustd14
if(NOT TARGET gtest OR NOT TARGET gmock_main)
# Download and unpack googletest at configure time.
diff --git a/METADATA b/METADATA
index eac4f3d..ab7bdf7 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/cpu_features.git"
}
- version: "v0.7.0"
+ version: "v0.8.0"
license_type: NOTICE
last_upgrade_date {
- year: 2022
- month: 3
- day: 8
+ year: 2023
+ month: 4
+ day: 27
}
}
diff --git a/README.md b/README.md
index 6091845..ee0ce70 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,44 @@
# cpu_features
-[![Linux Status][linux_svg]][linux_link]
-[![Macos Status][macos_svg]][macos_link]
-[![Windows Status][windows_svg]][windows_link]
-
-[linux_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_linux.yml/badge.svg?branch=main
-[linux_link]: https://github.com/google/cpu_features/actions/workflows/amd64_linux.yml
-[macos_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_macos.yml/badge.svg?branch=main
-[macos_link]: https://github.com/google/cpu_features/actions/workflows/amd64_macos.yml
-[windows_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_windows.yml/badge.svg?branch=main
-[windows_link]: https://github.com/google/cpu_features/actions/workflows/amd64_windows.yml
A cross-platform C library to retrieve CPU features (such as available
instructions) at runtime.
+# GitHub-CI Status
+
+[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
+[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
+[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
+[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
+[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml
+
## Table of Contents
- [Design Rationale](#rationale)
@@ -152,14 +178,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
<a name="support"></a>
## What's supported
-| | x86³ | ARM | AArch64 | MIPS⁴ | POWER |
-|---------|:----:|:-------:|:-------:|:-------:|:-------:|
-| Android | yes² | yes¹ | yes¹ | yes¹ | N/A |
-| iOS | N/A | not yet | not yet | N/A | N/A |
-| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ |
-| MacOs | yes² | N/A | not yet | N/A | no |
-| Windows | yes² | not yet | not yet | N/A | N/A |
-| FreeBSD | yes² | not yet | not yet | not yet | not yet |
+| | 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 |
1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
@@ -196,23 +222,39 @@ Please check the [CMake build instructions](cmake/README.md).
<a name="quickstart"></a>
### Quickstart
- - Run `list_cpu_features`
-```sh
-cmake -S. -Bbuild -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release
-cmake --build build --config Release -j
-./build/list_cpu_features --json
-```
+- Run `list_cpu_features`
+ ```sh
+ cmake -S. -Bbuild -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release
+ cmake --build build --config Release -j
+ ./build/list_cpu_features --json
+ ```
-_Note_: Use `--target ALL_BUILD` on the second line for `Visual Studio` and `XCode`.
+ _Note_: Use `--target ALL_BUILD` on the second line for `Visual Studio` and `XCode`.
- - run tests
-```sh
-cmake -S. -Bbuild -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
-cmake --build build --config Debug -j
-cmake --build build --config Debug --target test
-```
+- run tests
+ ```sh
+ cmake -S. -Bbuild -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
+ cmake --build build --config Debug -j
+ cmake --build build --config Debug --target test
+ ```
+
+ _Note_: Use `--target RUN_TESTS` on the last line for `Visual Studio` and `--target RUN_TEST` for `XCode`.
+
+
+- install `cpu_features`
+ ```sh
+ cmake --build build --config Release --target install -v
+ ```
+
+ _Note_: Use `--target INSTALL` for `Visual Studio`.
-_Note_: Use `--target RUN_TESTS` on the last line for `Visual Studio` and `--target RUN_TEST` for `XCode`.
+ _Note_: When using `Makefile` or `XCode` generator, you can use
+ [`DESTDIR`](https://www.gnu.org/software/make/manual/html_node/DESTDIR.html)
+ to install on a local repository.<br>
+ e.g.
+ ```sh
+ cmake --build build --config Release --target install -v -- DESTDIR=install
+ ```
<a name="bindings"></a>
## Community bindings
@@ -223,6 +265,8 @@ Links provided here are not affiliated with Google but are kindly provided by th
- https://github.com/toor1245/cpu_features.NET
- Python
- https://github.com/Narasimha1997/py_cpu
+ - Java
+ - https://github.com/aecsocket/cpu-features-java
_Send PR to showcase your wrapper here_
diff --git a/WORKSPACE b/WORKSPACE
index 104c459..c26a772 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,21 +1,17 @@
workspace(name = "com_google_cpufeatures")
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
-http_archive(
+git_repository(
name = "com_google_googletest",
- sha256 = "269cebe2be1f607f91f52630ff5bec3275b948c65d4bac323ebd05e90d84f7a9",
- strip_prefix = "googletest-e2239ee6043f73722e7aa812a459f54a28552929",
- urls = ["https://github.com/google/googletest/archive/e2239ee6043f73722e7aa812a459f54a28552929.zip"],
+ tag = "release-1.11.0",
+ remote = "https://github.com/google/googletest.git",
)
-http_archive(
+git_repository(
name = "bazel_skylib",
- sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d",
- urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz",
- "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz",
- ],
+ tag = "1.2.0",
+ remote = "https://github.com/bazelbuild/bazel-skylib.git",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
diff --git a/bazel/ci/README.md b/bazel/ci/README.md
new file mode 100644
index 0000000..c5fcde9
--- /dev/null
+++ b/bazel/ci/README.md
@@ -0,0 +1,5 @@
+## Usage
+To build tests with bazel
+```sh
+bazel test -s --verbose_failures //...
+```
diff --git a/ci/README.md b/ci/README.md
deleted file mode 100644
index e370136..0000000
--- a/ci/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# GitHub-CI Status
-| OS | amd64 | AArch64 | ARM | MIPS |
-|:-------- | :----: | :-----: | :-: | :--: |
-| FreeBSD | [![Status][freebsd_svg]][freebsd_link] | N/A | N/A | N/A |
-| Linux | [![Status][linux_svg]][linux_link] | [![Status][linux_aarch64_svg]][linux_aarch64_link] | [![Status][linux_arm_svg]][linux_arm_link] | [![Status][linux_mips_svg]][linux_mips_link] |
-| MacOS | [![Status][macos_svg]][macos_link] | N/A | N/A | N/A |
-| Windows | [![Status][windows_svg]][windows_link] | N/A | N/A | N/A |
-
-[freebsd_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd.yml/badge.svg?branch=main
-[freebsd_link]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd.yml
-
-[linux_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_linux.yml/badge.svg?branch=main
-[linux_link]: https://github.com/google/cpu_features/actions/workflows/amd64_linux.yml
-[linux_aarch64_svg]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux.yml/badge.svg?branch=main
-[linux_aarch64_link]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux.yml
-[linux_arm_svg]: https://github.com/google/cpu_features/actions/workflows/arm_linux.yml/badge.svg?branch=main
-[linux_arm_link]: https://github.com/google/cpu_features/actions/workflows/arm_linux.yml
-[linux_mips_svg]: https://github.com/google/cpu_features/actions/workflows/mips_linux.yml/badge.svg?branch=main
-[linux_mips_link]: https://github.com/google/cpu_features/actions/workflows/mips_linux.yml
-
-[macos_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_macos.yml/badge.svg?branch=main
-[macos_link]: https://github.com/google/cpu_features/actions/workflows/amd64_macos.yml
-
-[windows_svg]: https://github.com/google/cpu_features/actions/workflows/amd64_windows.yml/badge.svg?branch=main
-[windows_link]: https://github.com/google/cpu_features/actions/workflows/amd64_windows.yml
-
-## Makefile/Docker testing
-To test the build on various distro, we are using docker containers and a Makefile for orchestration.
-
-pros:
-* You are independent of third party CI runner config
- (e.g. [github action virtual-environnments](https://github.com/actions/virtual-environments)).
-* You can run it locally on your linux system.
-* Most CI provide runners with docker and Makefile installed.
-
-cons:
-* Only GNU/Linux distro supported.
-
-### Usage
-To get the help simply type:
-```sh
-make
-```
-
-note: you can also use from top directory
-```sh
-make --directory=ci
-```
-
-### Example
-For example to test mips32 inside an container:
-```sh
-make mips32_test
-```
-
-### Docker layers
-Dockerfile is splitted in several stages.
-
-![docker](doc/docker.svg)
-
-
-## Makefile/Vagrant testing
-To test build for FreeBSD we are using Vagrant and VirtualBox box.
-
-This is similar to the docker stuff but use `vagrant` as `docker` cli and
-VirtuaBox to replace the docker engine daemon.
diff --git a/cmake/README.md b/cmake/README.md
index b2d96c4..de33b23 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 `cpu_features` target to the `target_link_libraries()` section of
+3- Add the `CpuFeature::cpu_features` target to the `target_link_libraries()` section of
your executable or of your library.
## Disabling tests
diff --git a/ci/Makefile b/cmake/ci/Makefile
index 47ea30a..f655fc3 100644
--- a/ci/Makefile
+++ b/cmake/ci/Makefile
@@ -45,11 +45,19 @@ help:
@echo -e "\t\t${BOLD}armeb-linux-gnueabihf${RESET} (linaro toolchain)"
@echo -e "\t\t${BOLD}armeb-linux-gnueabi${RESET} (linaro toolchain)"
@echo -e "\t\t${BOLD}aarch64-linux-gnu${RESET} (linaro toolchain)"
+ @echo -e "\t\t${BOLD}aarch64${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}aarch64_be-linux-gnu${RESET} (linaro toolchain)"
+ @echo -e "\t\t${BOLD}aarch64be${RESET} (bootlin toolchain)"
@echo -e "\t\t${BOLD}mips32${RESET} (codespace toolchain)"
@echo -e "\t\t${BOLD}mips64${RESET} (codespace toolchain)"
@echo -e "\t\t${BOLD}mips32el${RESET} (codespace toolchain)"
@echo -e "\t\t${BOLD}mips64el${RESET} (codespace toolchain)"
+ @echo -e "\t\t${BOLD}ppc${RESET} (bootlin toolchain)"
+ @echo -e "\t\t${BOLD}ppc64${RESET} (bootlin toolchain)"
+ @echo -e "\t\t${BOLD}ppc64le${RESET} (bootlin toolchain)"
+ @echo -e "\t\t${BOLD}riscv32${RESET} (bootlin toolchain)"
+ @echo -e "\t\t${BOLD}riscv64${RESET} (bootlin toolchain)"
+ @echo -e "\t\t${BOLD}s390x${RESET} (bootlin toolchain)"
@echo
@echo -e "\tWith ${BOLD}<toolchain_stage>${RESET}:"
@echo -e "\t\t${BOLD}env${RESET}"
@@ -113,7 +121,7 @@ $(targets_amd64): amd64_%: docker/amd64/Dockerfile
--tag ${IMAGE}:amd64_$* \
--target=$* \
-f $< \
- ..
+ ../..
#$(info Create targets: save_amd64 $(addprefix save_amd64_, $(STAGES)) (debug).)
save_targets_amd64 = $(addprefix save_amd64_, $(STAGES))
@@ -143,9 +151,13 @@ $(clean_targets_amd64): clean_amd64_%:
## TOOLCHAIN ##
###############
TOOLCHAIN_TARGETS = \
+ aarch64 aarch64be \
arm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi armeb-linux-gnueabihf armeb-linux-gnueabi \
aarch64-linux-gnu aarch64_be-linux-gnu \
- mips32 mips32el mips64 mips64el
+ mips32 mips32el mips64 mips64el \
+ ppc ppc64 ppc64le \
+ riscv32 riscv64 \
+ s390x
TOOLCHAIN_STAGES = env devel build test
define toolchain-stage-target =
#$$(info STAGE: $1)
@@ -160,7 +172,7 @@ $$(targets_toolchain_$1): %_$1: docker/toolchain/Dockerfile
--build-arg TARGET=$$* \
--target=$1 \
-f $$< \
- ..
+ ../..
#$$(info Create targets: save_toolchain_$1 $(addprefix save_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))) (debug).)
save_targets_toolchain_$1 = $(addprefix save_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
diff --git a/cmake/ci/README.md b/cmake/ci/README.md
new file mode 100644
index 0000000..0d898d8
--- /dev/null
+++ b/cmake/ci/README.md
@@ -0,0 +1,40 @@
+## Makefile/Docker testing
+To test the build on various distro, we are using docker containers and a Makefile for orchestration.
+
+pros:
+* You are independent of third party CI runner config
+ (e.g. [github action virtual-environnments](https://github.com/actions/virtual-environments)).
+* You can run it locally on your linux system.
+* Most CI provide runners with docker and Makefile installed.
+
+cons:
+* Only GNU/Linux distro supported.
+
+### Usage
+To get the help simply type:
+```sh
+make
+```
+
+note: you can also use from top directory
+```sh
+make --directory=cmake/ci
+```
+
+### Example
+For example to test mips32 inside an container:
+```sh
+make mips32_test
+```
+
+### Docker layers
+Dockerfile is splitted in several stages.
+
+![docker](doc/docker.svg)
+
+
+## Makefile/Vagrant testing
+To test build for FreeBSD we are using Vagrant and VirtualBox box.
+
+This is similar to the docker stuff but use `vagrant` as `docker` cli and
+VirtuaBox to replace the docker engine daemon.
diff --git a/ci/doc/docker.dot b/cmake/ci/doc/docker.dot
index a00ef1f..a00ef1f 100644
--- a/ci/doc/docker.dot
+++ b/cmake/ci/doc/docker.dot
diff --git a/ci/doc/docker.svg b/cmake/ci/doc/docker.svg
index bd9bd6d..bd9bd6d 100644
--- a/ci/doc/docker.svg
+++ b/cmake/ci/doc/docker.svg
diff --git a/ci/doc/generate_image.sh b/cmake/ci/doc/generate_image.sh
index 15f1774..15f1774 100755
--- a/ci/doc/generate_image.sh
+++ b/cmake/ci/doc/generate_image.sh
diff --git a/ci/docker/amd64/Dockerfile b/cmake/ci/docker/amd64/Dockerfile
index 9b25e28..2cc3270 100644
--- a/ci/docker/amd64/Dockerfile
+++ b/cmake/ci/docker/amd64/Dockerfile
@@ -38,7 +38,7 @@ COPY --from=build /usr/local /usr/local/
FROM install_env AS install_devel
WORKDIR /home/sample
-COPY ci/sample .
+COPY cmake/ci/sample .
FROM install_devel AS install_build
RUN cmake -S. -Bbuild
diff --git a/ci/docker/toolchain/Dockerfile b/cmake/ci/docker/toolchain/Dockerfile
index 1bf25ed..1bf25ed 100644
--- a/ci/docker/toolchain/Dockerfile
+++ b/cmake/ci/docker/toolchain/Dockerfile
diff --git a/ci/sample/CMakeLists.txt b/cmake/ci/sample/CMakeLists.txt
index b60e92f..b60e92f 100644
--- a/ci/sample/CMakeLists.txt
+++ b/cmake/ci/sample/CMakeLists.txt
diff --git a/ci/sample/main.cpp b/cmake/ci/sample/main.cpp
index 45ec651..45ec651 100644
--- a/ci/sample/main.cpp
+++ b/cmake/ci/sample/main.cpp
diff --git a/ci/vagrant/freebsd/Vagrantfile b/cmake/ci/vagrant/freebsd/Vagrantfile
index 7ef7bfa..6234ff6 100644
--- a/ci/vagrant/freebsd/Vagrantfile
+++ b/cmake/ci/vagrant/freebsd/Vagrantfile
@@ -49,11 +49,11 @@ Vagrant.configure("2") do |config|
#config.vm.synced_folder "../../..", "/home/vagrant/project"
config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
- config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/"
- config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/"
- config.vm.provision "file", source: "../../../include", destination: "$HOME/project/"
- config.vm.provision "file", source: "../../../src", destination: "$HOME/project/"
- config.vm.provision "file", source: "../../../test", destination: "$HOME/project/"
+ config.vm.provision "file", source: "../../../../CMakeLists.txt", destination: "$HOME/project/"
+ config.vm.provision "file", source: "../../../../cmake", destination: "$HOME/project/"
+ config.vm.provision "file", source: "../../../../include", destination: "$HOME/project/"
+ config.vm.provision "file", source: "../../../../src", destination: "$HOME/project/"
+ config.vm.provision "file", source: "../../../../test", destination: "$HOME/project/"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
@@ -99,4 +99,9 @@ Vagrant.configure("2") do |config|
cd project
cmake --build build --target test -v
SHELL
+ config.vm.provision "test", type: "shell", inline:<<-SHELL
+ set -x
+ cd project
+ cmake --build build --target install -v
+ SHELL
end
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index 6a2f76a..215b567 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -39,7 +39,7 @@
#define CPU_FEATURES_ARCH_ARM
#endif
-#if defined(__aarch64__)
+#if (defined(__aarch64__) || defined(_M_ARM64))
#define CPU_FEATURES_ARCH_AARCH64
#endif
@@ -63,6 +63,26 @@
#define CPU_FEATURES_ARCH_PPC
#endif
+#if defined(__s390x__)
+#define CPU_FEATURES_ARCH_S390X
+#endif
+
+#if defined(__riscv)
+#define CPU_FEATURES_ARCH_RISCV
+#endif
+
+#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32
+#define CPU_FEATURES_ARCH_RISCV32
+#endif
+
+#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
+#define CPU_FEATURES_ARCH_RISCV64
+#endif
+
+#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 128
+#define CPU_FEATURES_ARCH_RISCV128
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Os
////////////////////////////////////////////////////////////////////////////////
@@ -224,8 +244,121 @@
#else
#define CPU_FEATURES_COMPILED_MIPS_MSA 0
#endif // defined(__mips_msa)
+#if defined(__mips3d)
+#define CPU_FEATURES_COMPILED_MIPS_MIPS3D 1
+#else
+#define CPU_FEATURES_COMPILED_MIPS_MIPS3D 0
+#endif
#endif // defined(CPU_FEATURES_ARCH_MIPS)
+#if defined(CPU_FEATURES_ARCH_RISCV)
+#if defined(__riscv_e)
+#define CPU_FEATURES_COMPILED_RISCV_E 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_E 0
+#endif
+#if defined(__riscv_i)
+#define CPU_FEATURES_COMPILED_RISCV_I 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_I 0
+#endif
+#if defined(__riscv_m)
+#define CPU_FEATURES_COMPILED_RISCV_M 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_M 0
+#endif
+#if defined(__riscv_a)
+#define CPU_FEATURES_COMPILED_RISCV_A 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_A 0
+#endif
+#if defined(__riscv_f)
+#define CPU_FEATURES_COMPILED_RISCV_F 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_F 0
+#endif
+#if defined(__riscv_d)
+#define CPU_FEATURES_COMPILED_RISCV_D 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_D 0
+#endif
+#if defined(__riscv_q)
+#define CPU_FEATURES_COMPILED_RISCV_Q 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_Q 0
+#endif
+#if defined(__riscv_c)
+#define CPU_FEATURES_COMPILED_RISCV_C 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_C 0
+#endif
+#if defined(__riscv_v)
+#define CPU_FEATURES_COMPILED_RISCV_V 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_V 0
+#endif
+#if defined(__riscv_zba)
+#define CPU_FEATURES_COMPILED_RISCV_ZBA 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZBA 0
+#endif
+#if defined(__riscv_zbb)
+#define CPU_FEATURES_COMPILED_RISCV_ZBB 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZBB 0
+#endif
+#if defined(__riscv_zbc)
+#define CPU_FEATURES_COMPILED_RISCV_ZBC 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZBC 0
+#endif
+#if defined(__riscv_zbs)
+#define CPU_FEATURES_COMPILED_RISCV_ZBS 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZBS 0
+#endif
+#if defined(__riscv_zfh)
+#define CPU_FEATURES_COMPILED_RISCV_ZFH 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZFH 0
+#endif
+#if defined(__riscv_zfhmin)
+#define CPU_FEATURES_COMPILED_RISCV_ZFHMIN 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZFHMIN 0
+#endif
+#if defined(__riscv_zknd)
+#define CPU_FEATURES_COMPILED_RISCV_ZKND 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKND 0
+#endif
+#if defined(__riscv_zkne)
+#define CPU_FEATURES_COMPILED_RISCV_ZKNE 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKNE 0
+#endif
+#if defined(__riscv_zknh)
+#define CPU_FEATURES_COMPILED_RISCV_ZKNH 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKNH 0
+#endif
+#if defined(__riscv_zksed)
+#define CPU_FEATURES_COMPILED_RISCV_ZKSED 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKSED 0
+#endif
+#if defined(__riscv_zksh)
+#define CPU_FEATURES_COMPILED_RISCV_ZKSH 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKSH 0
+#endif
+#if defined(__riscv_zkr)
+#define CPU_FEATURES_COMPILED_RISCV_ZKR 1
+#else
+#define CPU_FEATURES_COMPILED_RISCV_ZKR 0
+#endif
+#endif // defined(CPU_FEATURES_ARCH_RISCV)
+
////////////////////////////////////////////////////////////////////////////////
// Utils
////////////////////////////////////////////////////////////////////////////////
@@ -242,6 +375,8 @@
// Communicates to the compiler that the function is now deprecated
#if defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
#define CPU_FEATURES_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif defined(CPU_FEATURES_COMPILER_MSC)
+#define CPU_FEATURES_DEPRECATED(message) __declspec(deprecated(message))
#else
#define CPU_FEATURES_DEPRECATED(message)
#endif
diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h
index 1b57d21..d124b5f 100644
--- a/include/cpuinfo_aarch64.h
+++ b/include/cpuinfo_aarch64.h
@@ -12,6 +12,100 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+////////////////////////////////////////////////////////////////////////////////
+// A note on Windows AArch64 implementation
+////////////////////////////////////////////////////////////////////////////////
+
+// Getting cpu info via EL1 system registers is not possible, so we delegate it
+// to the Windows API (i.e., IsProcessorFeaturePresent and GetNativeSystemInfo).
+// The `implementer`, `variant` and `part` fields of the `Aarch64Info` struct
+// are not used, so they are set to 0. To get `revision` we use
+// `wProcessorRevision` from `SYSTEM_INFO`.
+//
+// Cryptographic Extension:
+// -----------------------------------------------------------------------------
+// According to documentation Arm Architecture Reference Manual for
+// A-profile architecture. A2.3 The Armv8 Cryptographic Extension. The Armv8.0
+// Cryptographic Extension provides instructions for the acceleration of
+// encryption and decryption, and includes the following features: FEAT_AES,
+// FEAT_PMULL, FEAT_SHA1, FEAT_SHA256.
+// see: https://developer.arm.com/documentation/ddi0487/latest
+//
+// We use `PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE` to detect all Armv8.0 crypto
+// features. This value reports all features or nothing, so even if you only
+// have support FEAT_AES and FEAT_PMULL, it will still return false.
+//
+// From Armv8.2, an implementation of the Armv8.0 Cryptographic Extension can
+// include either or both of:
+//
+// • The AES functionality, including support for multiplication of 64-bit
+// polynomials. The ID_AA64ISAR0_EL1.AES field indicates whether this
+// functionality is supported.
+// • The SHA1 and SHA2-256 functionality. The ID_AA64ISAR0_EL1.{SHA2, SHA1}
+// fields indicate whether this functionality is supported.
+//
+// ID_AA64ISAR0_EL1.AES, bits [7:4]:
+// Indicates support for AES instructions in AArch64 state. Defined values are:
+// - 0b0000 No AES instructions implemented.
+// - 0b0001 AESE, AESD, AESMC, and AESIMC instructions implemented.
+// - 0b0010 As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit
+// data quantities.
+//
+// FEAT_AES implements the functionality identified by the value 0b0001.
+// FEAT_PMULL implements the functionality identified by the value 0b0010.
+// From Armv8, the permitted values are 0b0000 and 0b0010.
+//
+// ID_AA64ISAR0_EL1.SHA1, bits [11:8]:
+// Indicates support for SHA1 instructions in AArch64 state. Defined values are:
+// - 0b0000 No SHA1 instructions implemented.
+// - 0b0001 SHA1C, SHA1P, SHA1M, SHA1H, SHA1SU0, and SHA1SU1 instructions
+// implemented.
+//
+// FEAT_SHA1 implements the functionality identified by the value 0b0001.
+// From Armv8, the permitted values are 0b0000 and 0b0001.
+// If the value of ID_AA64ISAR0_EL1.SHA2 is 0b0000, this field must have the
+// value 0b0000.
+//
+// ID_AA64ISAR0_EL1.SHA2, bits [15:12]:
+// Indicates support for SHA2 instructions in AArch64 state. Defined values are:
+// - 0b0000 No SHA2 instructions implemented.
+// - 0b0001 Implements instructions: SHA256H, SHA256H2, SHA256SU0, and
+// SHA256SU1.
+// - 0b0010 Implements instructions:
+// • SHA256H, SHA256H2, SHA256SU0, and SHA256SU1.
+// • SHA512H, SHA512H2, SHA512SU0, and SHA512SU1.
+//
+// FEAT_SHA256 implements the functionality identified by the value 0b0001.
+// FEAT_SHA512 implements the functionality identified by the value 0b0010.
+//
+// In Armv8, the permitted values are 0b0000 and 0b0001.
+// From Armv8.2, the permitted values are 0b0000, 0b0001, and 0b0010.
+//
+// If the value of ID_AA64ISAR0_EL1.SHA1 is 0b0000, this field must have the
+// value 0b0000.
+//
+// If the value of this field is 0b0010, ID_AA64ISAR0_EL1.SHA3
+// must have the value 0b0001.
+//
+// Other cryptographic features that we cannot detect such as sha512, sha3, sm3,
+// sm4, sveaes, svepmull, svesha3, svesm4 we set to 0.
+//
+// FP/SIMD:
+// -----------------------------------------------------------------------------
+// FP/SIMD must be implemented on all Armv8.0 implementations, but
+// implementations targeting specialized markets may support the following
+// combinations:
+//
+// • No NEON or floating-point.
+// • Full floating-point and SIMD support with exception trapping.
+// • Full floating-point and SIMD support without exception trapping.
+//
+// ref:
+// https://developer.arm.com/documentation/den0024/a/AArch64-Floating-point-and-NEON
+//
+// So, we use `PF_ARM_VFP_32_REGISTERS_AVAILABLE`,
+// `PF_ARM_NEON_INSTRUCTIONS_AVAILABLE` to detect `asimd` and `fp`
+
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
@@ -72,16 +166,20 @@ typedef struct {
int rng : 1; // True random number generator support.
int bti : 1; // Branch target identification.
int mte : 1; // Memory tagging extension.
+ int ecv : 1; // Enhanced counter virtualization.
+ int afp : 1; // Alternate floating-point behaviour.
+ int rpres : 1; // 12-bit reciprocal (square root) estimate precision.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
typedef struct {
Aarch64Features features;
- int implementer;
- int variant;
- int part;
- int revision;
+ int implementer; // We set 0 for Windows.
+ int variant; // We set 0 for Windows.
+ int part; // We set 0 for Windows.
+ int revision; // We use GetNativeSystemInfo to get processor revision for
+ // Windows.
} Aarch64Info;
Aarch64Info GetAarch64Info(void);
@@ -141,6 +239,9 @@ typedef enum {
AARCH64_RNG,
AARCH64_BTI,
AARCH64_MTE,
+ AARCH64_ECV,
+ AARCH64_AFP,
+ AARCH64_RPRES,
AARCH64_LAST_,
} Aarch64FeaturesEnum;
diff --git a/include/cpuinfo_mips.h b/include/cpuinfo_mips.h
index 9e5e7fc..321d3c8 100644
--- a/include/cpuinfo_mips.h
+++ b/include/cpuinfo_mips.h
@@ -21,11 +21,20 @@
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
- int msa : 1; // MIPS SIMD Architecture
- // https://www.mips.com/products/architectures/ase/simd/
- int eva : 1; // Enhanced Virtual Addressing
- // https://www.mips.com/products/architectures/mips64/
- int r6 : 1; // True if is release 6 of the processor.
+ int msa : 1; // MIPS SIMD Architecture
+ // https://www.mips.com/products/architectures/ase/simd/
+ int eva : 1; // Enhanced Virtual Addressing
+ // https://www.mips.com/products/architectures/mips64/
+ int r6 : 1; // True if is release 6 of the processor.
+ int mips16 : 1; // Compressed instructions
+ int mdmx : 1; // MIPS Digital Media Extension
+ int mips3d : 1; // 3D graphics acceleration
+ // MIPS(r) Architecture for Programmers, Volume IV-c
+ int smart : 1; // Smart-card cryptography
+ // MIPS(r) Architecture for Programmers, Volume IV-d
+ int dsp : 1; // Digital Signal Processing
+ // MIPS(r) Architecture for Programmers, Volume IV-e
+ // https://www.mips.com/products/architectures/ase/dsp/
// Make sure to update MipsFeaturesEnum below if you add a field here.
} MipsFeatures;
@@ -43,6 +52,11 @@ typedef enum {
MIPS_MSA,
MIPS_EVA,
MIPS_R6,
+ MIPS_MIPS16,
+ MIPS_MDMX,
+ MIPS_MIPS3D,
+ MIPS_SMART,
+ MIPS_DSP,
MIPS_LAST_,
} MipsFeaturesEnum;
diff --git a/include/cpuinfo_riscv.h b/include/cpuinfo_riscv.h
new file mode 100644
index 0000000..1fa7aa5
--- /dev/null
+++ b/include/cpuinfo_riscv.h
@@ -0,0 +1,72 @@
+// 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.
+
+#ifndef CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
+#define CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
+
+#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
+
+#if !defined(CPU_FEATURES_ARCH_RISCV)
+#error "Including cpuinfo_riscv.h from a non-riscv target."
+#endif
+
+CPU_FEATURES_START_CPP_NAMESPACE
+
+typedef struct {
+ // Base
+ int RV32I : 1; // Base Integer Instruction Set, 32-bit
+ int RV64I : 1; // Base Integer Instruction Set, 64-bit
+
+ // Extension
+ int M : 1; // Standard Extension for Integer Multiplication/Division
+ int A : 1; // Standard Extension for Atomic Instructions
+ int F : 1; // Standard Extension for Single-Precision Floating-Point
+ int D : 1; // Standard Extension for Double-Precision Floating-Point
+ int Q : 1; // Standard Extension for Quad-Precision Floating-Point
+ int C : 1; // Standard Extension for Compressed Instructions
+ int V : 1; // Standard Extension for Vector Instructions
+ int Zicsr : 1; // Control and Status Register (CSR)
+ int Zifencei : 1; // Instruction-Fetch Fence
+} RiscvFeatures;
+
+typedef struct {
+ RiscvFeatures features;
+ char uarch[64]; // 0 terminated string
+ char vendor[64]; // 0 terminated string
+} RiscvInfo;
+
+typedef enum {
+ RISCV_RV32I,
+ RISCV_RV64I,
+ RISCV_M,
+ RISCV_A,
+ RISCV_F,
+ RISCV_D,
+ RISCV_Q,
+ RISCV_C,
+ RISCV_V,
+ RISCV_Zicsr,
+ RISCV_Zifencei,
+ RISCV_LAST_,
+} RiscvFeaturesEnum;
+
+RiscvInfo GetRiscvInfo(void);
+int GetRiscvFeaturesEnumValue(const RiscvFeatures* features,
+ RiscvFeaturesEnum value);
+const char* GetRiscvFeaturesEnumName(RiscvFeaturesEnum);
+
+CPU_FEATURES_END_CPP_NAMESPACE
+
+#endif // CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
diff --git a/include/cpuinfo_s390x.h b/include/cpuinfo_s390x.h
new file mode 100644
index 0000000..48864de
--- /dev/null
+++ b/include/cpuinfo_s390x.h
@@ -0,0 +1,108 @@
+// Copyright 2022 IBM
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
+#define CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
+
+#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
+
+CPU_FEATURES_START_CPP_NAMESPACE
+
+typedef struct {
+ int esan3: 1; // instructions named N3, "backported" to esa-mode
+ int zarch: 1; // z/Architecture mode active
+ int stfle: 1; // store-facility-list-extended
+ int msa: 1; // message-security assist
+ int ldisp: 1; // long-displacement
+ int eimm: 1; // extended-immediate
+ int dfp: 1; // decimal floating point & perform floating point operation
+ int edat: 1; // huge page support
+ int etf3eh: 1; // extended-translation facility 3 enhancement
+ int highgprs: 1; // 64-bit register support for 31-bit processes
+ int te: 1; // transactional execution
+ int vx: 1; // vector extension facility
+ int vxd: 1; // vector-packed-decimal facility
+ int vxe: 1; // vector-enhancement facility 1
+ int gs: 1; // guarded-storage facility
+ int vxe2: 1; // vector-enhancements facility 2
+ int vxp: 1; // vector-packed-decimal-enhancement facility
+ int sort: 1; // enhanced-sort facility
+ int dflt: 1; // deflate-conversion facility
+ int vxp2: 1; // vector-packed-decimal-enhancement facility 2
+ int nnpa: 1; // neural network processing assist facility
+ int pcimio: 1; // PCI mio facility
+ int sie: 1; // virtualization support
+
+ // Make sure to update S390XFeaturesEnum below if you add a field here.
+} S390XFeatures;
+
+typedef struct {
+ S390XFeatures features;
+} S390XInfo;
+
+S390XInfo GetS390XInfo(void);
+
+typedef struct {
+ char platform[64]; // 0 terminated string
+} S390XPlatformTypeStrings;
+
+typedef struct {
+ int num_processors; // -1 if N/A
+ S390XPlatformTypeStrings type;
+} S390XPlatformStrings;
+
+S390XPlatformStrings GetS390XPlatformStrings(void);
+
+////////////////////////////////////////////////////////////////////////////////
+// Introspection functions
+
+typedef enum {
+ S390_ESAN3,
+ S390_ZARCH,
+ S390_STFLE,
+ S390_MSA,
+ S390_LDISP,
+ S390_EIMM,
+ S390_DFP,
+ S390_EDAT,
+ S390_ETF3EH,
+ S390_HIGHGPRS,
+ S390_TE,
+ S390_VX,
+ S390_VXD,
+ S390_VXE,
+ S390_GS,
+ S390_VXE2,
+ S390_VXP,
+ S390_SORT,
+ S390_DFLT,
+ S390_VXP2,
+ S390_NNPA,
+ S390_PCIMIO,
+ S390_SIE,
+ S390X_LAST_,
+} S390XFeaturesEnum;
+
+int GetS390XFeaturesEnumValue(const S390XFeatures* features, S390XFeaturesEnum value);
+
+const char* GetS390XFeaturesEnumName(S390XFeaturesEnum);
+
+CPU_FEATURES_END_CPP_NAMESPACE
+
+#if !defined(CPU_FEATURES_ARCH_S390X)
+#error "Including cpuinfo_s390x.h from a non-s390x target."
+#endif
+
+#endif // CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h
index 88daca4..e897500 100644
--- a/include/cpuinfo_x86.h
+++ b/include/cpuinfo_x86.h
@@ -60,6 +60,7 @@ typedef struct {
int sse4a : 1;
int avx : 1;
+ int avx_vnni : 1;
int avx2 : 1;
int avx512f : 1;
@@ -76,11 +77,12 @@ typedef struct {
int avx512bitalg : 1;
int avx512vpopcntdq : 1;
int avx512_4vnniw : 1;
- int avx512_4vbmi2 : 1;
+ int avx512_4vbmi2 : 1; // Note: this is an alias to avx512_4fmaps.
int avx512_second_fma : 1;
int avx512_4fmaps : 1;
int avx512_bf16 : 1;
int avx512_vp2intersect : 1;
+ int avx512_fp16 : 1;
int amx_bf16 : 1;
int amx_tile : 1;
int amx_int8 : 1;
@@ -97,6 +99,14 @@ typedef struct {
int dca : 1;
int ss : 1;
int adx : 1;
+ int lzcnt : 1; // Note: this flag is called ABM for AMD, LZCNT for Intel.
+ int gfni : 1;
+ int movdiri : 1;
+ int movdir64b : 1;
+ int fs_rep_mov : 1; // Fast short REP MOV
+ 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
// Make sure to update X86FeaturesEnum below if you add a field here.
} X86Features;
@@ -114,59 +124,64 @@ X86Info GetX86Info(void);
// Returns cache hierarchy informations.
// Can call cpuid multiple times.
-// Only works on Intel CPU at the moment.
CacheInfo GetX86CacheInfo(void);
typedef enum {
X86_UNKNOWN,
- ZHAOXIN_ZHANGJIANG, // ZhangJiang
- ZHAOXIN_WUDAOKOU, // WuDaoKou
- ZHAOXIN_LUJIAZUI, // LuJiaZui
- ZHAOXIN_YONGFENG, // YongFeng
- INTEL_80486, // 80486
- INTEL_P5, // P5
- INTEL_LAKEMONT, // LAKEMONT
- INTEL_CORE, // CORE
- INTEL_PNR, // PENRYN
- INTEL_NHM, // NEHALEM
- INTEL_ATOM_BNL, // BONNELL
- INTEL_WSM, // WESTMERE
- INTEL_SNB, // SANDYBRIDGE
- INTEL_IVB, // IVYBRIDGE
- INTEL_ATOM_SMT, // SILVERMONT
- INTEL_HSW, // HASWELL
- INTEL_BDW, // BROADWELL
- INTEL_SKL, // SKYLAKE
- INTEL_ATOM_GMT, // GOLDMONT
- INTEL_KBL, // KABY LAKE
- INTEL_CFL, // COFFEE LAKE
- INTEL_WHL, // WHISKEY LAKE
- INTEL_CNL, // CANNON LAKE
- INTEL_ICL, // ICE LAKE
- INTEL_TGL, // TIGER LAKE
- INTEL_SPR, // SAPPHIRE RAPIDS
- INTEL_ADL, // ALDER LAKE
- INTEL_RCL, // ROCKET LAKE
- INTEL_KNIGHTS_M, // KNIGHTS MILL
- INTEL_KNIGHTS_L, // KNIGHTS LANDING
- INTEL_KNIGHTS_F, // KNIGHTS FERRY
- INTEL_KNIGHTS_C, // KNIGHTS CORNER
- INTEL_NETBURST, // NETBURST
- AMD_HAMMER, // K8 HAMMER
- AMD_K10, // K10
- AMD_K11, // K11
- AMD_K12, // K12
- AMD_BOBCAT, // K14 BOBCAT
- AMD_PILEDRIVER, // K15 PILEDRIVER
- AMD_STREAMROLLER, // K15 STREAMROLLER
- AMD_EXCAVATOR, // K15 EXCAVATOR
- AMD_BULLDOZER, // K15 BULLDOZER
- AMD_JAGUAR, // K16 JAGUAR
- AMD_PUMA, // K16 PUMA
- AMD_ZEN, // K17 ZEN
- AMD_ZEN_PLUS, // K17 ZEN+
- AMD_ZEN2, // K17 ZEN 2
- AMD_ZEN3, // K19 ZEN 3
+ ZHAOXIN_ZHANGJIANG, // ZhangJiang
+ ZHAOXIN_WUDAOKOU, // WuDaoKou
+ ZHAOXIN_LUJIAZUI, // LuJiaZui
+ ZHAOXIN_YONGFENG, // YongFeng
+ INTEL_80486, // 80486
+ INTEL_P5, // P5
+ INTEL_LAKEMONT, // LAKEMONT
+ INTEL_CORE, // CORE
+ INTEL_PNR, // PENRYN
+ INTEL_NHM, // NEHALEM
+ INTEL_ATOM_BNL, // BONNELL
+ INTEL_WSM, // WESTMERE
+ INTEL_SNB, // SANDYBRIDGE
+ INTEL_IVB, // IVYBRIDGE
+ INTEL_ATOM_SMT, // SILVERMONT
+ INTEL_HSW, // HASWELL
+ INTEL_BDW, // BROADWELL
+ INTEL_SKL, // SKYLAKE
+ INTEL_CCL, // CASCADELAKE
+ INTEL_ATOM_GMT, // GOLDMONT
+ INTEL_ATOM_GMT_PLUS, // GOLDMONT+
+ INTEL_ATOM_TMT, // TREMONT
+ INTEL_KBL, // KABY LAKE
+ INTEL_CFL, // COFFEE LAKE
+ INTEL_WHL, // WHISKEY LAKE
+ INTEL_CML, // COMET LAKE
+ INTEL_CNL, // CANNON LAKE
+ INTEL_ICL, // ICE LAKE
+ INTEL_TGL, // TIGER LAKE
+ INTEL_SPR, // SAPPHIRE RAPIDS
+ INTEL_ADL, // ALDER LAKE
+ INTEL_RCL, // ROCKET LAKE
+ INTEL_RPL, // RAPTOR LAKE
+ INTEL_KNIGHTS_M, // KNIGHTS MILL
+ INTEL_KNIGHTS_L, // KNIGHTS LANDING
+ INTEL_KNIGHTS_F, // KNIGHTS FERRY
+ INTEL_KNIGHTS_C, // KNIGHTS CORNER
+ INTEL_NETBURST, // NETBURST
+ AMD_HAMMER, // K8 HAMMER
+ AMD_K10, // K10
+ AMD_K11, // K11
+ AMD_K12, // K12 LLANO
+ AMD_BOBCAT, // K14 BOBCAT
+ AMD_PILEDRIVER, // K15 PILEDRIVER
+ AMD_STREAMROLLER, // K15 STREAMROLLER
+ AMD_EXCAVATOR, // K15 EXCAVATOR
+ AMD_BULLDOZER, // K15 BULLDOZER
+ AMD_JAGUAR, // K16 JAGUAR
+ AMD_PUMA, // K16 PUMA
+ AMD_ZEN, // K17 ZEN
+ AMD_ZEN_PLUS, // K17 ZEN+
+ AMD_ZEN2, // K17 ZEN 2
+ AMD_ZEN3, // K19 ZEN 3
+ AMD_ZEN4, // K19 ZEN 4
X86_MICROARCHITECTURE_LAST_,
} X86Microarchitecture;
@@ -211,6 +226,7 @@ typedef enum {
X86_SSE4_2,
X86_SSE4A,
X86_AVX,
+ X86_AVX_VNNI,
X86_AVX2,
X86_AVX512F,
X86_AVX512CD,
@@ -226,11 +242,12 @@ typedef enum {
X86_AVX512BITALG,
X86_AVX512VPOPCNTDQ,
X86_AVX512_4VNNIW,
- X86_AVX512_4VBMI2,
+ X86_AVX512_4VBMI2, // Note: this is an alias to X86_AVX512_4FMAPS.
X86_AVX512_SECOND_FMA,
X86_AVX512_4FMAPS,
X86_AVX512_BF16,
X86_AVX512_VP2INTERSECT,
+ X86_AVX512_FP16,
X86_AMX_BF16,
X86_AMX_TILE,
X86_AMX_INT8,
@@ -245,6 +262,14 @@ typedef enum {
X86_DCA,
X86_SS,
X86_ADX,
+ X86_LZCNT,
+ X86_GFNI,
+ X86_MOVDIRI,
+ X86_MOVDIR64B,
+ X86_FS_REP_MOV,
+ X86_FZ_REP_MOVSB,
+ X86_FS_REP_STOSB,
+ X86_FS_REP_CMPSB_SCASB,
X86_LAST_,
} X86FeaturesEnum;
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index d7fc782..3290cc9 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -80,6 +80,9 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define AARCH64_HWCAP2_RNG (1UL << 16)
#define AARCH64_HWCAP2_BTI (1UL << 17)
#define AARCH64_HWCAP2_MTE (1UL << 18)
+#define AARCH64_HWCAP2_ECV (1UL << 19)
+#define AARCH64_HWCAP2_AFP (1UL << 20)
+#define AARCH64_HWCAP2_RPRES (1UL << 21)
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#define ARM_HWCAP_SWP (1UL << 0)
@@ -114,6 +117,13 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define MIPS_HWCAP_R6 (1UL << 0)
#define MIPS_HWCAP_MSA (1UL << 1)
#define MIPS_HWCAP_CRC32 (1UL << 2)
+#define MIPS_HWCAP_MIPS16 (1UL << 3)
+#define MIPS_HWCAP_MDMX (1UL << 4)
+#define MIPS_HWCAP_MIPS3D (1UL << 5)
+#define MIPS_HWCAP_SMARTMIPS (1UL << 6)
+#define MIPS_HWCAP_DSP (1UL << 7)
+#define MIPS_HWCAP_DSP2 (1UL << 8)
+#define MIPS_HWCAP_DSP3 (1UL << 9)
// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h
#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H
@@ -166,6 +176,46 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
#endif
+// https://elixir.bootlin.com/linux/v6.0-rc6/source/arch/s390/include/asm/elf.h
+#define HWCAP_S390_ESAN3 1
+#define HWCAP_S390_ZARCH 2
+#define HWCAP_S390_STFLE 4
+#define HWCAP_S390_MSA 8
+#define HWCAP_S390_LDISP 16
+#define HWCAP_S390_EIMM 32
+#define HWCAP_S390_DFP 64
+#define HWCAP_S390_HPAGE 128
+#define HWCAP_S390_ETF3EH 256
+#define HWCAP_S390_HIGH_GPRS 512
+#define HWCAP_S390_TE 1024
+#define HWCAP_S390_VX 2048
+#define HWCAP_S390_VXRS HWCAP_S390_VX
+#define HWCAP_S390_VXD 4096
+#define HWCAP_S390_VXRS_BCD HWCAP_S390_VXD
+#define HWCAP_S390_VXE 8192
+#define HWCAP_S390_VXRS_EXT HWCAP_S390_VXE
+#define HWCAP_S390_GS 16384
+#define HWCAP_S390_VXRS_EXT2 32768
+#define HWCAP_S390_VXRS_PDE 65536
+#define HWCAP_S390_SORT 131072
+#define HWCAP_S390_DFLT 262144
+#define HWCAP_S390_VXRS_PDE2 524288
+#define HWCAP_S390_NNPA 1048576
+#define HWCAP_S390_PCI_MIO 2097152
+#define HWCAP_S390_SIE 4194304
+
+// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h
+#define RISCV_HWCAP_32 0x32
+#define RISCV_HWCAP_64 0x64
+#define RISCV_HWCAP_128 0x128
+#define RISCV_HWCAP_M (1UL << ('M' - 'A'))
+#define RISCV_HWCAP_A (1UL << ('A' - 'A'))
+#define RISCV_HWCAP_F (1UL << ('F' - 'A'))
+#define RISCV_HWCAP_D (1UL << ('D' - 'A'))
+#define RISCV_HWCAP_Q (1UL << ('Q' - 'A'))
+#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
+#define RISCV_HWCAP_V (1UL << ('V' - 'A'))
+
typedef struct {
unsigned long hwcaps;
unsigned long hwcaps2;
diff --git a/include/internal/windows_utils.h b/include/internal/windows_utils.h
new file mode 100644
index 0000000..3348c52
--- /dev/null
+++ b/include/internal/windows_utils.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_
+#define CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_
+
+#include "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_OS_WINDOWS
+
+#include <windows.h> // IsProcessorFeaturePresent
+
+// modern WinSDK winnt.h contains newer features detection definitions
+#if !defined(PF_SSSE3_INSTRUCTIONS_AVAILABLE)
+#define PF_SSSE3_INSTRUCTIONS_AVAILABLE 36
+#endif
+
+#if !defined(PF_SSE4_1_INSTRUCTIONS_AVAILABLE)
+#define PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37
+#endif
+
+#if !defined(PF_SSE4_2_INSTRUCTIONS_AVAILABLE)
+#define PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38
+#endif
+
+#if !defined(PF_ARM_VFP_32_REGISTERS_AVAILABLE)
+#define PF_ARM_VFP_32_REGISTERS_AVAILABLE 18
+#endif
+
+#if !defined(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19
+#endif
+
+#if !defined(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 30
+#endif
+
+#if !defined(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 31
+#endif
+
+#if !defined(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE 34
+#endif
+
+#if !defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 43
+#endif
+
+#if !defined(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE 44
+#endif
+
+#if !defined(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE)
+#define PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE 45
+#endif
+
+#endif // CPU_FEATURES_OS_WINDOWS
+#endif // CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_
diff --git a/scripts/generate_badges.d b/scripts/generate_badges.d
new file mode 100644
index 0000000..bf5aa54
--- /dev/null
+++ b/scripts/generate_badges.d
@@ -0,0 +1,165 @@
+import std.algorithm : each, map, cartesianProduct, filter, joiner, sort, uniq;
+import std.array : array;
+import std.conv : to;
+import std.format;
+import std.range : chain, only;
+import std.stdio;
+import std.traits : EnumMembers;
+
+enum BuildSystem
+{
+ CMake,
+ Bazel
+}
+
+enum Cpu
+{
+ amd64,
+ AArch64,
+ ARM,
+ MIPS,
+ POWER,
+ RISCV,
+ s390x,
+}
+
+enum Os
+{
+ Linux,
+ FreeBSD,
+ MacOS,
+ Windows,
+}
+
+struct Badge
+{
+const:
+
+ Cpu cpu;
+ Os os;
+ BuildSystem build_system;
+
+ 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));
+ }
+
+ string link_ref()
+ {
+ return format("[l%s]", id());
+ }
+
+ string image_ref()
+ {
+ return format("[i%s]", id());
+ }
+
+ bool enabled()
+ {
+ final switch (build_system)
+ {
+ case BuildSystem.CMake:
+ return os == Os.Linux || cpu == Cpu.amd64;
+ case BuildSystem.Bazel:
+ return os == Os.Linux && cpu == Cpu.amd64;
+ }
+ }
+
+ string text()
+ {
+ if (enabled())
+ return format("[![]%s]%s", image_ref, link_ref);
+ return format("![]%s", disabled_image_ref);
+ }
+
+ string disabled_image_link()
+ {
+ return format("%s: https://img.shields.io/badge/%s-N%%2FA-lightgrey", disabled_image_ref, build_system);
+ }
+
+ string filename()
+ {
+ import std.uni : toLower;
+
+ return toLower(format("%s_%s_%s.yml", cpu, os, build_system));
+ }
+
+ string link_decl()
+ {
+ 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);
+ }
+}
+
+auto tableHeader(in Cpu[] cpus)
+{
+ return chain(only("Os"), cpus.map!(to!string)).array;
+}
+
+auto tableAlignment(in Cpu[] cpus)
+{
+ return chain(only(":--"), cpus.map!(v => "--:")).array;
+}
+
+auto tableCell(Range)(in Os os, in Cpu cpu, Range badges)
+{
+ return badges
+ .filter!(b => b.cpu == cpu && b.os == os)
+ .map!(b => b.text())
+ .joiner("<br/>")
+ .to!string;
+}
+
+auto tableRow(Range)(in Os os, in Cpu[] cpus, Range badges)
+{
+ return chain(only(os.to!string), cpus.map!(cpu => 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;
+}
+
+auto table(Range)(in Os[] oses, in Cpu[] cpus, Range badges)
+{
+ return chain(only(tableHeader(cpus)), only(tableAlignment(cpus)), tableRows(oses, cpus, badges));
+}
+
+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)
+ .map!(b => b.disabled_image_link())
+ .array
+ .sort
+ .uniq
+ .each!writeln;
+
+ badges
+ .filter!(b => b.enabled)
+ .map!(b => [b.link_decl(), b.image_decl()])
+ .joiner()
+ .array
+ .sort
+ .uniq
+ .each!writeln;
+}
diff --git a/scripts/make_release.sh b/scripts/make_release.sh
index 01e85f7..25b59f9 100755
--- a/scripts/make_release.sh
+++ b/scripts/make_release.sh
@@ -69,4 +69,7 @@ git commit -m"Release ${GIT_TAG}"
echo -e "${ACTION}Create new tag${NOCOLOR}"
git tag ${GIT_TAG}
-echo -e "${FINISHED}Local release is ready. Run `git push origin --tags`${NOCOLOR}"
+echo -e "${FINISHED}Manual steps:${NOCOLOR}"
+echo -e "${FINISHED} - Push the tag upstream 'git push origin ${GIT_TAG}'${NOCOLOR}"
+echo -e "${FINISHED} - Create a new release https://github.com/google/cpu_features/releases/new${NOCOLOR}"
+echo -e "${FINISHED} - Update the Release Notes 'gren release --override'${NOCOLOR}"
diff --git a/scripts/run_integration.sh b/scripts/run_integration.sh
index 645cb6a..053ffa9 100755
--- a/scripts/run_integration.sh
+++ b/scripts/run_integration.sh
@@ -22,7 +22,7 @@ function unpack() {
if [[ ! -d "${DESTINATION}" ]] ; then
echo "Downloading ${URL}..."
local -r ARCHIVE_NAME=$(basename "${URL}")
- test -f "${ARCHIVE_NAME}" || wget --no-verbose "${URL}"
+ [[ -f "${ARCHIVE_NAME}" ]] || wget --no-verbose "${URL}"
extract "${ARCHIVE_NAME}"
rm -f "${ARCHIVE_NAME}"
fi
@@ -33,7 +33,7 @@ function install_qemu() {
>&2 echo 'QEMU is disabled !'
return 0
fi
- local -r QEMU_VERSION=${QEMU_VERSION:=5.2.0}
+ local -r QEMU_VERSION=${QEMU_VERSION:=7.1.0}
local -r QEMU_TARGET=${QEMU_ARCH}-linux-user
if echo "${QEMU_VERSION} ${QEMU_TARGET}" | cmp --silent "${QEMU_INSTALL}/.build" -; then
@@ -70,11 +70,7 @@ function install_qemu() {
--disable-opengl \
--disable-sdl \
--disable-virglrenderer \
- --disable-vte \
- --enable-modules
-
- # --static Not supported on Archlinux
- # so we use --enable-modules
+ --disable-vte
# wrapper on ninja
make -j8
@@ -140,16 +136,107 @@ QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
QEMU_ARGS+=( -E LD_LIBRARY_PATH=/lib )
}
+function expand_bootlin_config() {
+ # ref: https://toolchains.bootlin.com/
+ local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
+
+ case "${TARGET}" in
+ "aarch64")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64/tarballs/aarch64--glibc--stable-2021.11-1.tar.bz2"
+ local -r GCC_PREFIX="aarch64"
+ ;;
+ "aarch64be")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64be/tarballs/aarch64be--glibc--stable-2021.11-1.tar.bz2"
+ local -r GCC_PREFIX="aarch64_be"
+ ;;
+ "ppc64le")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64le-power8/tarballs/powerpc64le-power8--glibc--stable-2021.11-1.tar.bz2"
+ local -r GCC_PREFIX="powerpc64le"
+ ;;
+ "ppc64")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64-power8/tarballs/powerpc64-power8--glibc--stable-2021.11-1.tar.bz2"
+ local -r GCC_PREFIX="powerpc64"
+ ;;
+ "ppc")
+ #local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc-e500mc/tarballs/powerpc-e500mc--glibc--stable-2021.11-1.tar.bz2"
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc-440fp/tarballs/powerpc-440fp--glibc--stable-2021.11-1.tar.bz2"
+ local -r GCC_PREFIX="powerpc"
+ ;;
+ "riscv32")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv32-ilp32d/tarballs/riscv32-ilp32d--glibc--bleeding-edge-2022.08-1.tar.bz2"
+ local -r GCC_PREFIX="riscv32"
+ ;;
+ "riscv64")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv64-lp64d/tarballs/riscv64-lp64d--glibc--stable-2022.08-1.tar.bz2"
+ local -r GCC_PREFIX="riscv64"
+ ;;
+ "s390x")
+ local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/s390x-z13/tarballs/s390x-z13--glibc--stable-2022.08-1.tar.bz2"
+ local -r GCC_PREFIX="s390x"
+ ;;
+ *)
+ >&2 echo 'unknown power platform'
+ exit 1 ;;
+ esac
+
+ local -r TOOLCHAIN_RELATIVE_DIR="${TARGET}"
+ unpack "${TOOLCHAIN_URL}" "${TOOLCHAIN_RELATIVE_DIR}"
+ local -r EXTRACT_DIR="${ARCHIVE_DIR}/$(basename ${TOOLCHAIN_URL%.tar.bz2})"
+
+ local -r TOOLCHAIN_DIR=${ARCHIVE_DIR}/${TOOLCHAIN_RELATIVE_DIR}
+ if [[ -d "${EXTRACT_DIR}" ]]; then
+ mv "${EXTRACT_DIR}" "${TOOLCHAIN_DIR}"
+ fi
+
+ local -r SYSROOT_DIR="${TOOLCHAIN_DIR}/${GCC_PREFIX}-buildroot-linux-gnu/sysroot"
+ #local -r STAGING_DIR=${SYSROOT_DIR}-stage
+
+ # Write a Toolchain file
+ # note: This is manadatory to use a file in order to have the CMake variable
+ # 'CMAKE_CROSSCOMPILING' set to TRUE.
+ # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
+ cat >"${TOOLCHAIN_FILE}" <<EOL
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR ${GCC_PREFIX})
+
+set(CMAKE_SYSROOT ${SYSROOT_DIR})
+#set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
+
+set(tools ${TOOLCHAIN_DIR})
+
+set(CMAKE_C_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-gcc)
+set(CMAKE_C_FLAGS "${POWER_FLAGS}")
+set(CMAKE_CXX_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-g++)
+set(CMAKE_CXX_FLAGS "${POWER_FLAGS} -L${SYSROOT_DIR}/lib")
+
+set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR})
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+EOL
+
+CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
+QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
+QEMU_ARGS+=( -E LD_PRELOAD="${SYSROOT_DIR}/usr/lib/libstdc++.so.6:${SYSROOT_DIR}/lib/libgcc_s.so.1" )
+}
+
function expand_codescape_config() {
+ # https://www.mips.com/develop/tools/codescape-mips-sdk/mips-toolchain-configurations/
+ # mips-mti: MIPS32R6 and MIPS64R6
+ # mips-img: MIPS32R2 and MIPS64R2
+
# ref: https://codescape.mips.com/components/toolchain/2020.06-01/downloads.html
- # ref: https://codescape.mips.com/components/toolchain/2019.02-04/downloads.html
local -r DATE=2020.06-01
- #local -r DATE=2019.02-04
local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-6.x86_64.tar.gz
- #local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.IMG.Linux.CentOS-6.x86_64.tar.gz
- local -r GCC_URL=${CODESCAPE_URL}
local -r GCC_RELATIVE_DIR="mips-mti-linux-gnu/${DATE}"
+
+ # ref: https://codescape.mips.com/components/toolchain/2019.02-04/downloads.html
+ #local -r DATE=2019.02-04
+ #local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.IMG.Linux.CentOS-6.x86_64.tar.gz
#local -r GCC_RELATIVE_DIR="mips-img-linux-gnu/${DATE}"
+
+ local -r GCC_URL=${CODESCAPE_URL}
unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}"
local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
@@ -174,12 +261,14 @@ function expand_codescape_config() {
"mips64")
MIPS_FLAGS="-EB -mips64r6 -mabi=64"
FLAVOUR="mips-r6-hard"
+ #MIPS_FLAGS="-EB -mips64r2 -mabi=64"
#FLAVOUR="mips-r2-hard"
LIBC_DIR_SUFFIX="lib64"
;;
"mips64el")
MIPS_FLAGS="-EL -mips64r6 -mabi=64"
FLAVOUR="mipsel-r6-hard"
+ #MIPS_FLAGS="-EL -mips64r2 -mabi=64"
#FLAVOUR="mipsel-r2-hard"
LIBC_DIR_SUFFIX="lib64"
;;
@@ -203,13 +292,17 @@ set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
set(tools ${GCC_DIR})
+# R6
set(CMAKE_C_COMPILER \${tools}/bin/mips-mti-linux-gnu-gcc)
-#set(CMAKE_C_COMPILER \${tools}/bin/mips-img-linux-gnu-gcc)
set(CMAKE_C_FLAGS "${MIPS_FLAGS}")
-
set(CMAKE_CXX_COMPILER \${tools}/bin/mips-mti-linux-gnu-g++)
+set(CMAKE_CXX_FLAGS "${MIPS_FLAGS} -L${SYSROOT_DIR}/usr/lib64")
+
+# R2
+#set(CMAKE_C_COMPILER \${tools}/bin/mips-img-linux-gnu-gcc)
+#set(CMAKE_C_FLAGS "${MIPS_FLAGS}")
#set(CMAKE_CXX_COMPILER \${tools}/bin/mips-img-linux-gnu-g++)
-set(CMAKE_CXX_FLAGS "${MIPS_FLAGS}")
+#set(CMAKE_CXX_FLAGS "${MIPS_FLAGS}")
set(CMAKE_FIND_ROOT_PATH ${GCC_DIR})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
@@ -244,10 +337,15 @@ function run_test() {
RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[*]}"
cd "${BUILD_DIR}" || exit 2
+ declare -a TEST_BINARIES=()
+ TEST_BINARIES+=($(find "${BUILD_DIR}"/test -executable -type f))
+ TEST_BINARIES+=($(find "${BUILD_DIR}" -maxdepth 1 -executable -type f))
set -x
- for test_binary in "${BUILD_DIR}"/list_cpu_feature* ; do
+ set -e
+ for test_binary in ${TEST_BINARIES[*]} ; do
${RUN_CMD} "${test_binary}"
done
+ set +e
set +x
}
@@ -264,11 +362,16 @@ DESCRIPTION
\tYou MUST define the following variables before running this script:
\t* TARGET:
\t\tx86_64
-\t\taarch64-linux-gnu aarch64_be-linux-gnu
-\t\tarm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi
-\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi
-\t\tmips32 mips32el
-\t\tmips64 mips64el
+\t\taarch64 aarch64be (bootlin)
+\t\taarch64-linux-gnu aarch64_be-linux-gnu (linaro)
+\t\tarm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi (linaro)
+\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi (linaro)
+\t\tmips32 mips32el (codespace)
+\t\tmips64 mips64el (codespace)
+\t\tppc (bootlin)
+\t\tppc64 ppc64le (bootlin)
+\t\triscv32 riscv64 (bootlin)
+\t\ts390x (bootlin)
OPTIONS
\t-h --help: show this help text
@@ -326,7 +429,13 @@ function main() {
declare -r QEMU_ARCH=aarch64 ;;
aarch64_be-linux-gnu)
expand_linaro_config
- declare -r QEMU_ARCH=DISABLED ;;
+ declare -r QEMU_ARCH=aarch64_be ;;
+ aarch64)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=aarch64 ;;
+ aarch64be)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=aarch64_be ;;
mips32)
expand_codescape_config
declare -r QEMU_ARCH=mips ;;
@@ -339,6 +448,24 @@ function main() {
mips64el)
expand_codescape_config
declare -r QEMU_ARCH=mips64el ;;
+ ppc64le)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=ppc64le ;;
+ ppc64)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=ppc64 ;;
+ ppc)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=ppc ;;
+ riscv32)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=riscv32 ;;
+ riscv64)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=riscv64 ;;
+ s390x)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=s390x ;;
*)
>&2 echo "Unknown TARGET '${TARGET}'..."
exit 1 ;;
diff --git a/src/impl_aarch64_linux_or_android.c b/src/impl_aarch64_linux_or_android.c
index 745beb9..ef923d9 100644
--- a/src/impl_aarch64_linux_or_android.c
+++ b/src/impl_aarch64_linux_or_android.c
@@ -74,7 +74,10 @@
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_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"
diff --git a/src/impl_aarch64_windows.c b/src/impl_aarch64_windows.c
new file mode 100644
index 0000000..f103909
--- /dev/null
+++ b/src/impl_aarch64_windows.c
@@ -0,0 +1,138 @@
+// 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_AARCH64
+#ifdef CPU_FEATURES_OS_WINDOWS
+
+#include "cpuinfo_aarch64.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(AARCH64_FP, fp, , , ) \
+ LINE(AARCH64_ASIMD, asimd, , , ) \
+ LINE(AARCH64_EVTSTRM, evtstrm, , , ) \
+ LINE(AARCH64_AES, aes, , , ) \
+ LINE(AARCH64_PMULL, pmull, , , ) \
+ LINE(AARCH64_SHA1, sha1, , , ) \
+ LINE(AARCH64_SHA2, sha2, , , ) \
+ LINE(AARCH64_CRC32, crc32, , , ) \
+ LINE(AARCH64_ATOMICS, atomics, , , ) \
+ LINE(AARCH64_FPHP, fphp, , , ) \
+ LINE(AARCH64_ASIMDHP, asimdhp, , , ) \
+ LINE(AARCH64_CPUID, cpuid, , , ) \
+ LINE(AARCH64_ASIMDRDM, asimdrdm, , , ) \
+ LINE(AARCH64_JSCVT, jscvt, , , ) \
+ LINE(AARCH64_FCMA, fcma, , , ) \
+ LINE(AARCH64_LRCPC, lrcpc, , , ) \
+ LINE(AARCH64_DCPOP, dcpop, , , ) \
+ LINE(AARCH64_SHA3, sha3, , , ) \
+ LINE(AARCH64_SM3, sm3, , , ) \
+ LINE(AARCH64_SM4, sm4, , , ) \
+ LINE(AARCH64_ASIMDDP, asimddp, , , ) \
+ LINE(AARCH64_SHA512, sha512, , , ) \
+ LINE(AARCH64_SVE, sve, , , ) \
+ LINE(AARCH64_ASIMDFHM, asimdfhm, , , ) \
+ LINE(AARCH64_DIT, dit, , , ) \
+ LINE(AARCH64_USCAT, uscat, , , ) \
+ LINE(AARCH64_ILRCPC, ilrcpc, , , ) \
+ LINE(AARCH64_FLAGM, flagm, , , ) \
+ LINE(AARCH64_SSBS, ssbs, , , ) \
+ LINE(AARCH64_SB, sb, , , ) \
+ LINE(AARCH64_PACA, paca, , , ) \
+ LINE(AARCH64_PACG, pacg, , , ) \
+ LINE(AARCH64_DCPODP, dcpodp, , , ) \
+ LINE(AARCH64_SVE2, sve2, , , ) \
+ LINE(AARCH64_SVEAES, sveaes, , , ) \
+ LINE(AARCH64_SVEPMULL, svepmull, , , ) \
+ LINE(AARCH64_SVEBITPERM, svebitperm, , , ) \
+ LINE(AARCH64_SVESHA3, svesha3, , , ) \
+ LINE(AARCH64_SVESM4, svesm4, , , ) \
+ LINE(AARCH64_FLAGM2, flagm2, , , ) \
+ LINE(AARCH64_FRINT, frint, , , ) \
+ LINE(AARCH64_SVEI8MM, svei8mm, , , ) \
+ LINE(AARCH64_SVEF32MM, svef32mm, , , ) \
+ LINE(AARCH64_SVEF64MM, svef64mm, , , ) \
+ LINE(AARCH64_SVEBF16, svebf16, , , ) \
+ LINE(AARCH64_I8MM, i8mm, , , ) \
+ LINE(AARCH64_BF16, bf16, , , ) \
+ LINE(AARCH64_DGH, dgh, , , ) \
+ LINE(AARCH64_RNG, rng, , , ) \
+ LINE(AARCH64_BTI, bti, , , ) \
+ LINE(AARCH64_MTE, mte, , , ) \
+ LINE(AARCH64_ECV, ecv, , , ) \
+ LINE(AARCH64_AFP, afp, , , ) \
+ LINE(AARCH64_RPRES, rpres, , , )
+#define INTROSPECTION_PREFIX Aarch64
+#define INTROSPECTION_ENUM_PREFIX AARCH64
+#include "define_introspection.inl"
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdbool.h>
+
+#include "internal/windows_utils.h"
+
+#ifdef CPU_FEATURES_MOCK_CPUID_AARCH64
+extern bool GetWindowsIsProcessorFeaturePresent(DWORD);
+extern WORD GetWindowsNativeSystemInfoProcessorRevision();
+#else // CPU_FEATURES_MOCK_CPUID_AARCH64
+static bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
+ return IsProcessorFeaturePresent(dwProcessorFeature);
+}
+
+static WORD GetWindowsNativeSystemInfoProcessorRevision() {
+ SYSTEM_INFO system_info;
+ GetNativeSystemInfo(&system_info);
+ return system_info.wProcessorRevision;
+}
+#endif
+
+static const Aarch64Info kEmptyAarch64Info;
+
+Aarch64Info GetAarch64Info(void) {
+ Aarch64Info info = kEmptyAarch64Info;
+ info.revision = GetWindowsNativeSystemInfoProcessorRevision();
+ info.features.fp =
+ GetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
+ info.features.asimd =
+ GetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
+ info.features.crc32 = GetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
+ info.features.asimddp =
+ GetWindowsIsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE);
+ info.features.jscvt = GetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE);
+ info.features.lrcpc = GetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE);
+ info.features.atomics = GetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE);
+
+
+ bool is_crypto_available = GetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
+ info.features.aes = is_crypto_available;
+ info.features.sha1 = is_crypto_available;
+ info.features.sha2 = is_crypto_available;
+ info.features.pmull = is_crypto_available;
+ return info;
+}
+
+#endif // CPU_FEATURES_OS_WINDOWS
+#endif // CPU_FEATURES_ARCH_AARCH64
diff --git a/src/impl_mips_linux_or_android.c b/src/impl_mips_linux_or_android.c
index 9a3dc2f..2322ecf 100644
--- a/src/impl_mips_linux_or_android.c
+++ b/src/impl_mips_linux_or_android.c
@@ -20,10 +20,15 @@
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
-#define INTROSPECTION_TABLE \
- LINE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
- LINE(MIPS_EVA, eva, "eva", 0, 0) \
- LINE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
+#define INTROSPECTION_TABLE \
+ LINE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
+ LINE(MIPS_EVA, eva, "eva", 0, 0) \
+ LINE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0) \
+ LINE(MIPS_MIPS16, mips16, "mips16", MIPS_HWCAP_MIPS16, 0) \
+ LINE(MIPS_MDMX, mdmx, "mdmx", MIPS_HWCAP_MDMX, 0) \
+ LINE(MIPS_MIPS3D, mips3d, "mips3d", MIPS_HWCAP_MIPS3D, 0) \
+ LINE(MIPS_SMART, smart, "smartmips", MIPS_HWCAP_SMARTMIPS, 0) \
+ LINE(MIPS_DSP, dsp, "dsp", MIPS_HWCAP_DSP, 0)
#define INTROSPECTION_PREFIX Mips
#define INTROSPECTION_ENUM_PREFIX MIPS
#include "define_introspection_and_hwcaps.inl"
diff --git a/src/impl_ppc_linux.c b/src/impl_ppc_linux.c
index 13a381a..46a72d7 100644
--- a/src/impl_ppc_linux.c
+++ b/src/impl_ppc_linux.c
@@ -69,6 +69,7 @@
LINE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
LINE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
PPC_FEATURE2_HTM_NO_SUSPEND)
+#undef PPC // Remove conflict with compiler generated preprocessor
#define INTROSPECTION_PREFIX PPC
#define INTROSPECTION_ENUM_PREFIX PPC
#include "define_introspection_and_hwcaps.inl"
diff --git a/src/impl_riscv_linux.c b/src/impl_riscv_linux.c
new file mode 100644
index 0000000..8abec6e
--- /dev/null
+++ b/src/impl_riscv_linux.c
@@ -0,0 +1,111 @@
+// 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 "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_RISCV
+#if defined(CPU_FEATURES_OS_LINUX)
+
+#include "cpuinfo_riscv.h"
+
+// According to
+// https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/riscv/cpus.yaml
+// isa string should match the following regex
+// ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
+//
+// This means we can test for features in this exact order except for Z
+// extensions.
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(RISCV_RV32I, RV32I, "rv32i", RISCV_HWCAP_32, 0) \
+ LINE(RISCV_RV64I, RV64I, "rv64i", RISCV_HWCAP_64, 0) \
+ LINE(RISCV_M, M, "m", RISCV_HWCAP_M, 0) \
+ LINE(RISCV_A, A, "a", RISCV_HWCAP_A, 0) \
+ LINE(RISCV_F, F, "f", RISCV_HWCAP_F, 0) \
+ LINE(RISCV_D, D, "d", RISCV_HWCAP_D, 0) \
+ LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \
+ LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \
+ LINE(RISCV_V, V, "v", RISCV_HWCAP_V, 0) \
+ LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \
+ LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0)
+#define INTROSPECTION_PREFIX Riscv
+#define INTROSPECTION_ENUM_PREFIX RISCV
+#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 RiscvInfo kEmptyRiscvInfo;
+
+static void HandleRiscVIsaLine(StringView line, RiscvFeatures* const features) {
+ for (size_t i = 0; i < RISCV_LAST_; ++i) {
+ StringView flag = str(kCpuInfoFlags[i]);
+ int index_of_flag = CpuFeatures_StringView_IndexOf(line, flag);
+ bool is_set = index_of_flag != -1;
+ kSetters[i](features, is_set);
+ if (is_set)
+ line = CpuFeatures_StringView_PopFront(line, index_of_flag + flag.size);
+ }
+}
+
+static bool HandleRiscVLine(const LineResult result, RiscvInfo* const info) {
+ StringView line = result.line;
+ StringView key, value;
+ if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+ if (CpuFeatures_StringView_IsEquals(key, str("isa"))) {
+ HandleRiscVIsaLine(value, &info->features);
+ } else if (CpuFeatures_StringView_IsEquals(key, str("uarch"))) {
+ int index = CpuFeatures_StringView_IndexOfChar(value, ',');
+ if (index == -1) return true;
+ StringView vendor = CpuFeatures_StringView_KeepFront(value, index);
+ StringView uarch = CpuFeatures_StringView_PopFront(value, index + 1);
+ CpuFeatures_StringView_CopyString(vendor, info->vendor,
+ sizeof(info->vendor));
+ CpuFeatures_StringView_CopyString(uarch, info->uarch,
+ sizeof(info->uarch));
+ }
+ }
+ return !result.eof;
+}
+
+static void FillProcCpuInfoData(RiscvInfo* const info) {
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ if (!HandleRiscVLine(StackLineReader_NextLine(&reader), info)) break;
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+}
+
+RiscvInfo GetRiscvInfo(void) {
+ RiscvInfo info = kEmptyRiscvInfo;
+ FillProcCpuInfoData(&info);
+ return info;
+}
+
+#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
+#endif // CPU_FEATURES_ARCH_RISCV
diff --git a/src/impl_s390x_linux.c b/src/impl_s390x_linux.c
new file mode 100644
index 0000000..2b8b865
--- /dev/null
+++ b/src/impl_s390x_linux.c
@@ -0,0 +1,120 @@
+// Copyright 2022 IBM.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_S390X
+#ifdef CPU_FEATURES_OS_LINUX
+
+#include "cpuinfo_s390x.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(S390_ESAN3, esan3, "esan3", HWCAP_S390_ESAN3, 0) \
+ LINE(S390_ZARCH, zarch, "zarch", HWCAP_S390_ZARCH, 0) \
+ LINE(S390_STFLE, stfle, "stfle", HWCAP_S390_STFLE, 0) \
+ LINE(S390_MSA, msa, "msa", HWCAP_S390_MSA, 0) \
+ LINE(S390_LDISP, ldisp, "ldisp", HWCAP_S390_LDISP, 0) \
+ LINE(S390_EIMM, eimm, "eimm", HWCAP_S390_EIMM, 0) \
+ LINE(S390_DFP, dfp, "dfp", HWCAP_S390_DFP, 0) \
+ LINE(S390_EDAT, edat, "edat", HWCAP_S390_HPAGE, 0) \
+ LINE(S390_ETF3EH, etf3eh, "etf3eh", HWCAP_S390_ETF3EH, 0) \
+ LINE(S390_HIGHGPRS, highgprs, "highgprs", HWCAP_S390_HIGH_GPRS, 0) \
+ LINE(S390_TE, te, "te", HWCAP_S390_TE, 0) \
+ LINE(S390_VX, vx, "vx", HWCAP_S390_VXRS, 0) \
+ LINE(S390_VXD, vxd, "vxd", HWCAP_S390_VXRS_BCD, 0) \
+ LINE(S390_VXE, vxe, "vxe", HWCAP_S390_VXRS_EXT, 0) \
+ LINE(S390_GS, gs, "gs", HWCAP_S390_GS, 0) \
+ LINE(S390_VXE2, vxe2, "vxe2", HWCAP_S390_VXRS_EXT2, 0) \
+ LINE(S390_VXP, vxp, "vxp", HWCAP_S390_VXRS_PDE, 0) \
+ LINE(S390_SORT, sort, "sort", HWCAP_S390_SORT, 0) \
+ LINE(S390_DFLT, dflt, "dflt", HWCAP_S390_DFLT, 0) \
+ LINE(S390_VXP2, vxp2, "vxp2", HWCAP_S390_VXRS_PDE2, 0) \
+ LINE(S390_NNPA, nnpa, "nnpa", HWCAP_S390_NNPA, 0) \
+ LINE(S390_PCIMIO, pcimio, "pcimio", HWCAP_S390_PCI_MIO, 0) \
+ LINE(S390_SIE, sie, "sie", HWCAP_S390_SIE, 0)
+#define INTROSPECTION_PREFIX S390X
+#define INTROSPECTION_ENUM_PREFIX S390X
+#include "define_introspection_and_hwcaps.inl"
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdbool.h>
+
+#include "internal/bit_utils.h"
+#include "internal/filesystem.h"
+#include "internal/hwcaps.h"
+#include "internal/stack_line_reader.h"
+#include "internal/string_view.h"
+
+static bool HandleS390XLine(const LineResult result,
+ S390XPlatformStrings* const strings) {
+ StringView line = result.line;
+ StringView key, value;
+ if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+ if (CpuFeatures_StringView_IsEquals(key, str("# processors"))) {
+ strings->num_processors = CpuFeatures_StringView_ParsePositiveNumber(value);
+ }
+ }
+ return !result.eof;
+}
+
+static void FillProcCpuInfoData(S390XPlatformStrings* const strings) {
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ if (!HandleS390XLine(StackLineReader_NextLine(&reader), strings)) {
+ break;
+ }
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+}
+
+static const S390XInfo kEmptyS390XInfo;
+
+S390XInfo GetS390XInfo(void) {
+ S390XInfo info = kEmptyS390XInfo;
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < S390X_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
+ return info;
+}
+
+static const S390XPlatformStrings kEmptyS390XPlatformStrings;
+
+S390XPlatformStrings GetS390XPlatformStrings(void) {
+ S390XPlatformStrings strings = kEmptyS390XPlatformStrings;
+ const char* platform = CpuFeatures_GetPlatformPointer();
+
+ FillProcCpuInfoData(&strings);
+
+ if (platform != NULL)
+ CpuFeatures_StringView_CopyString(str(platform), strings.type.platform,
+ sizeof(strings.type.platform));
+
+ return strings;
+}
+
+#endif // CPU_FEATURES_OS_LINUX
+#endif // CPU_FEATURES_ARCH_S390X
diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl
index 09f24b2..6a34bff 100644
--- a/src/impl_x86__base_implementation.inl
+++ b/src/impl_x86__base_implementation.inl
@@ -13,6 +13,76 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// A note on x86 SIMD instructions availability
+// -----------------------------------------------------------------------------
+// A number of conditions need to be met for an application to use SIMD
+// instructions:
+// 1. The CPU itself must support the instruction.
+// - we use `CPUID` to check whether the feature is supported.
+// 2. The OS must save and restore the associated SIMD register across context
+// switches, we check that:
+// - the CPU reports supporting hardware context switching instructions via
+// CPUID.1:ECX.XSAVE[bit 26]
+// - the OS reports supporting hardware context switching instructions via
+// CPUID.1:ECX.OSXSAVE[bit 27]
+// - the CPU extended control register 0 (XCR0) is set to save and restore the
+// needed SIMD registers
+//
+// Note that if `XSAVE`/`OSXSAVE` are missing, we delegate the detection to the
+// OS via the `DetectFeaturesFromOs` function or via microarchitecture
+// heuristics.
+//
+// Encoding
+// -----------------------------------------------------------------------------
+// X86Info contains fields such as vendor and brand_string that are ASCII
+// encoded strings. `vendor` length of characters is 13 and `brand_string` is 49
+// (with null terminated string). We use CPUID.1:E[D,C,B]X to get `vendor` and
+// CPUID.8000_000[4:2]:E[D,C,B,A]X to get `brand_string`
+//
+// Microarchitecture
+// -----------------------------------------------------------------------------
+// `GetX86Microarchitecture` function consists of check on vendor via
+// `IsVendorByX86Info`. We use `CPUID(family, model)` to define the vendor's
+// microarchitecture. In cases where the `family` and `model` is the same for
+// several microarchitectures we do a stepping check or in the worst case we
+// rely on parsing brand_string (see HasSecondFMA for an example). Details of
+// identification by `brand_string` can be found by reference:
+// https://en.wikichip.org/wiki/intel/microarchitectures/cascade_lake
+// https://www.intel.com/content/www/us/en/processors/processor-numbers.html
+
+// CacheInfo X86
+// -----------------------------------------------------------------------------
+// We use the CacheInfo struct to store information about cache levels. The
+// maximum number of levels is hardcoded but can be increased if needed. We have
+// full support of cache identification for the following processors:
+// • Intel:
+// ◦ modern processors:
+// we use `ParseCacheInfo` function with `leaf_id` 0x00000004.
+// ◦ old processors:
+// we parse descriptors via `GetCacheLevelInfo`, see Application Note
+// 485: Intel Processor Identification and CPUID Instruction.
+// • AMD:
+// ◦ modern processors:
+// we use `ParseCacheInfo` function with `leaf_id` 0x8000001D.
+// ◦ old processors:
+// we parse cache info using Fn8000_0005_E[A,B,C,D]X and
+// Fn8000_0006_E[A,B,C,D]X. See AMD CPUID Specification:
+// https://www.amd.com/system/files/TechDocs/25481.pdf.
+// • Hygon:
+// we reuse AMD cache detection implementation.
+// • Zhaoxin:
+// we reuse Intel cache detection implementation.
+//
+// Internal structures
+// -----------------------------------------------------------------------------
+// We use internal structures such as `Leaves` and `OsPreserves` to cache the
+// result of cpuid info and support of registers, since latency of CPUID
+// instruction is around ~100 cycles, see
+// https://www.agner.org/optimize/instruction_tables.pdf. Hence, we use
+// `ReadLeaves` function for `GetX86Info`, `GetCacheInfo` and
+// `FillX86BrandString` to read leaves and hold these values to avoid redundant
+// call on the same leaf.
+
#include <stdbool.h>
#include <string.h>
@@ -98,7 +168,7 @@ typedef struct {
Leaf leaf_80000004; // brand string
} Leaves;
-static Leaves ReadLeaves() {
+static Leaves ReadLeaves(void) {
const Leaf leaf_0 = GetCpuidLeaf(0, 0);
const uint32_t max_cpuid_leaf = leaf_0.eax;
const Leaf leaf_80000000 = GetCpuidLeaf(0x80000000, 0);
@@ -121,7 +191,6 @@ static Leaves ReadLeaves() {
////////////////////////////////////////////////////////////////////////////////
// OS support
-// TODO: Add documentation
////////////////////////////////////////////////////////////////////////////////
#define MASK_XMM 0x2
@@ -254,6 +323,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
const Leaf leaf_1 = leaves->leaf_1;
const Leaf leaf_7 = leaves->leaf_7;
const Leaf leaf_7_1 = leaves->leaf_7_1;
+ const Leaf leaf_80000001 = leaves->leaf_80000001;
const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
@@ -309,9 +379,17 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
features->clflushopt = IsBitSet(leaf_7.ebx, 23);
features->clwb = IsBitSet(leaf_7.ebx, 24);
features->sha = IsBitSet(leaf_7.ebx, 29);
+ features->gfni = IsBitSet(leaf_7.ecx, 8);
features->vaes = IsBitSet(leaf_7.ecx, 9);
features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
+ features->movdiri = IsBitSet(leaf_7.ecx, 27);
+ features->movdir64b = IsBitSet(leaf_7.ecx, 28);
+ features->fs_rep_mov = IsBitSet(leaf_7.edx, 4);
+ features->fz_rep_movsb = IsBitSet(leaf_7_1.eax, 10);
+ features->fs_rep_stosb = IsBitSet(leaf_7_1.eax, 11);
+ 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);
/////////////////////////////////////////////////////////////////////////////
// The following section is devoted to Vector Extensions.
@@ -340,6 +418,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
if (os_preserves->avx_registers) {
features->fma3 = IsBitSet(leaf_1.ecx, 12);
features->avx = IsBitSet(leaf_1.ecx, 28);
+ features->avx_vnni = IsBitSet(leaf_7_1.eax, 4);
features->avx2 = IsBitSet(leaf_7.ebx, 5);
}
if (os_preserves->avx512_registers) {
@@ -362,6 +441,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info,
features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3);
features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5);
features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8);
+ features->avx512_fp16 = IsBitSet(leaf_7.edx, 23);
}
if (os_preserves->amx_registers) {
features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
@@ -406,8 +486,8 @@ X86Info GetX86Info(void) {
IsVendor(leaves.leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
const bool is_hygon =
IsVendor(leaves.leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE);
- const bool is_zhaoxin =
- (IsVendor(leaves.leaf_0, CPU_FEATURES_VENDOR_CENTAUR_HAULS) ||
+ const bool is_zhaoxin =
+ (IsVendor(leaves.leaf_0, CPU_FEATURES_VENDOR_CENTAUR_HAULS) ||
IsVendor(leaves.leaf_0, CPU_FEATURES_VENDOR_SHANGHAI));
SetVendor(leaves.leaf_0, info.vendor);
if (is_intel || is_amd || is_hygon || is_zhaoxin) {
@@ -463,6 +543,15 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x06, 0x5C):
// https://en.wikipedia.org/wiki/Goldmont
return INTEL_ATOM_GMT;
+ case CPUID(0x06, 0x7A):
+ // https://en.wikichip.org/wiki/intel/microarchitectures/goldmont_plus
+ return INTEL_ATOM_GMT_PLUS;
+ case CPUID(0x06, 0x8A):
+ case CPUID(0x06, 0x96):
+ case CPUID(0x06, 0x9C):
+ // https://en.wikichip.org/wiki/intel/microarchitectures/tremont
+ return INTEL_ATOM_TMT;
+ case CPUID(0x06, 0x0E):
case CPUID(0x06, 0x0F):
case CPUID(0x06, 0x16):
// https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture)
@@ -503,10 +592,15 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikipedia.org/wiki/Broadwell_(microarchitecture)
return INTEL_BDW;
case CPUID(0x06, 0x4E):
- case CPUID(0x06, 0x55):
case CPUID(0x06, 0x5E):
// https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
return INTEL_SKL;
+ case CPUID(0x06, 0x55):
+ if (info->stepping >= 6 && info->stepping <= 7) {
+ // https://en.wikipedia.org/wiki/Cascade_Lake_(microprocessor)
+ return INTEL_CCL;
+ }
+ return INTEL_SKL;
case CPUID(0x06, 0x66):
// https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
return INTEL_CNL;
@@ -532,6 +626,8 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake
case 11:
return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture)
+ case 12:
+ return INTEL_CML; // https://en.wikichip.org/wiki/intel/microarchitectures/comet_lake
default:
return X86_UNKNOWN;
}
@@ -547,9 +643,18 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x06, 0x9A):
// https://en.wikichip.org/wiki/intel/microarchitectures/alder_lake
return INTEL_ADL;
+ case CPUID(0x06, 0xA5):
+ case CPUID(0x06, 0xA6):
+ // https://en.wikichip.org/wiki/intel/microarchitectures/comet_lake
+ return INTEL_CML;
case CPUID(0x06, 0xA7):
// https://en.wikichip.org/wiki/intel/microarchitectures/rocket_lake
return INTEL_RCL;
+ case CPUID(0x06, 0xB7):
+ case CPUID(0x06, 0xBA):
+ case CPUID(0x06, 0xBF):
+ // https://en.wikichip.org/wiki/intel/microarchitectures/raptor_lake
+ return INTEL_RPL;
case CPUID(0x06, 0x85):
// https://en.wikichip.org/wiki/intel/microarchitectures/knights_mill
return INTEL_KNIGHTS_M;
@@ -580,15 +685,15 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikichip.org/wiki/zhaoxin/microarchitectures/zhangjiang
return ZHAOXIN_ZHANGJIANG;
case CPUID(0x07, 0x1B):
- // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/wudaokou
- return ZHAOXIN_WUDAOKOU;
+ // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/wudaokou
+ return ZHAOXIN_WUDAOKOU;
case CPUID(0x07, 0x3B):
- // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/lujiazui
- return ZHAOXIN_LUJIAZUI;
+ // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/lujiazui
+ return ZHAOXIN_LUJIAZUI;
case CPUID(0x07, 0x5B):
- return ZHAOXIN_YONGFENG;
+ return ZHAOXIN_YONGFENG;
default:
- return X86_UNKNOWN;
+ return X86_UNKNOWN;
}
}
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_SHANGHAI)) {
@@ -598,15 +703,15 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikichip.org/wiki/zhaoxin/microarchitectures/zhangjiang
return ZHAOXIN_ZHANGJIANG;
case CPUID(0x07, 0x1B):
- // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/wudaokou
- return ZHAOXIN_WUDAOKOU;
+ // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/wudaokou
+ return ZHAOXIN_WUDAOKOU;
case CPUID(0x07, 0x3B):
- // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/lujiazui
- return ZHAOXIN_LUJIAZUI;
+ // https://en.wikichip.org/wiki/zhaoxin/microarchitectures/lujiazui
+ return ZHAOXIN_LUJIAZUI;
case CPUID(0x07, 0x5B):
- return ZHAOXIN_YONGFENG;
+ return ZHAOXIN_YONGFENG;
default:
- return X86_UNKNOWN;
+ return X86_UNKNOWN;
}
}
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_AUTHENTIC_AMD)) {
@@ -659,6 +764,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x11, 0x03):
// http://developer.amd.com/wordpress/media/2012/10/41788.pdf
return AMD_K11;
+ case CPUID(0x12, 0x00):
case CPUID(0x12, 0x01):
// https://www.amd.com/system/files/TechDocs/44739_12h_Rev_Gd.pdf
return AMD_K12;
@@ -671,9 +777,11 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikichip.org/wiki/amd/microarchitectures/bulldozer
return AMD_BULLDOZER;
case CPUID(0x15, 0x02):
+ case CPUID(0x15, 0x10):
case CPUID(0x15, 0x11):
case CPUID(0x15, 0x13):
// https://en.wikichip.org/wiki/amd/microarchitectures/piledriver
+ // https://www.amd.com/system/files/TechDocs/48931_15h_Mod_10h-1Fh_Rev_Guide.pdf
return AMD_PILEDRIVER;
case CPUID(0x15, 0x30):
case CPUID(0x15, 0x38):
@@ -685,6 +793,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
// https://en.wikichip.org/wiki/amd/microarchitectures/excavator
return AMD_EXCAVATOR;
case CPUID(0x16, 0x00):
+ case CPUID(0x16, 0x26):
return AMD_JAGUAR;
case CPUID(0x16, 0x30):
return AMD_PUMA;
@@ -704,15 +813,23 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x17, 0x71):
case CPUID(0x17, 0x90):
case CPUID(0x17, 0x98):
+ case CPUID(0x17, 0xA0):
// https://en.wikichip.org/wiki/amd/microarchitectures/zen_2
return AMD_ZEN2;
+ case CPUID(0x19, 0x00):
case CPUID(0x19, 0x01):
+ case CPUID(0x19, 0x08):
case CPUID(0x19, 0x21):
case CPUID(0x19, 0x30):
case CPUID(0x19, 0x40):
+ case CPUID(0x19, 0x44):
case CPUID(0x19, 0x50):
// https://en.wikichip.org/wiki/amd/microarchitectures/zen_3
return AMD_ZEN3;
+ case CPUID(0x19, 0x10):
+ case CPUID(0x19, 0x61):
+ // https://en.wikichip.org/wiki/amd/microarchitectures/zen_4
+ return AMD_ZEN4;
default:
return X86_UNKNOWN;
}
@@ -720,6 +837,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_HYGON_GENUINE)) {
switch (CPUID(info->family, info->model)) {
case CPUID(0x18, 0x00):
+ case CPUID(0x18, 0x01):
return AMD_ZEN;
}
}
@@ -1629,16 +1747,18 @@ static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id,
const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, leaf_id, index);
int cache_type_field = ExtractBitRange(leaf.eax, 4, 0);
CacheType cache_type;
- if (cache_type_field == 0)
- break;
- else if (cache_type_field == 1)
+ if (cache_type_field == 1)
cache_type = CPU_FEATURE_CACHE_DATA;
else if (cache_type_field == 2)
cache_type = CPU_FEATURE_CACHE_INSTRUCTION;
else if (cache_type_field == 3)
cache_type = CPU_FEATURE_CACHE_UNIFIED;
else
- break; // Should not occur as per documentation.
+ // Intel Processor Identification and the CPUID Instruction Application
+ // Note 485 page 37 Table 5-10. Deterministic Cache Parameters.
+ // We skip cache parsing in case null of cache type or cache type in the
+ // range of 4-31 according to documentation.
+ break;
int level = ExtractBitRange(leaf.eax, 7, 5);
int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
@@ -1659,6 +1779,115 @@ static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id,
if (info.size > 0) *old_info = info;
}
+typedef struct {
+ int level;
+ int cache_id;
+ CacheType cache_type;
+} CacheLevelInfoLegacyAMD;
+
+static int GetWaysLegacyAMD(int cache_level, const uint32_t cache_id) {
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 23
+ // CPUID.8000_0005_ECX[23:16] L1 data cache associativity.
+ // CPUID.8000_0005_EDX[23:16] L1 instruction cache associativity.
+ if (cache_level == 1) {
+ return ExtractBitRange(cache_id, 23, 16);
+ }
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 24
+ // See Table 4: L2/L3 Cache and TLB Associativity Field Definition.
+ // CPUID.8000_0006_ECX[15:12] L2 cache associativity.
+ // CPUID.8000_0006_EDX[15:12] L3 cache associativity.
+ const int ways = ExtractBitRange(cache_id, 15, 12);
+ switch (ways) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x4:
+ return ways;
+ case 0x6:
+ return 8;
+ case 0x8:
+ return 16;
+ case 0xA:
+ return 32;
+ case 0xB:
+ return 48;
+ case 0xC:
+ return 64;
+ case 0xD:
+ return 96;
+ case 0xE:
+ return 128;
+ case 0xF:
+ return 255;
+ default:
+ return -1; // Reserved
+ }
+}
+
+static int GetCacheSizeLegacyAMD(int cache_level, const uint32_t cache_id) {
+ switch (cache_level) {
+ case 1:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 23
+ // CPUID.8000_0005_ECX[31:24] L1 data cache size in KB.
+ // CPUID.8000_0005_EDX[31:24] L1 instruction cache size KB.
+ return ExtractBitRange(cache_id, 31, 24);
+ case 2:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 25
+ // CPUID.8000_0006_ECX[31:16] L2 cache size in KB.
+ return ExtractBitRange(cache_id, 31, 16);
+ case 3:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 25
+ // CPUID.8000_0006_EDX[31:18] L3 cache size.
+ // Specifies the L3 cache size is within the following range:
+ // (L3Size[31:18] * 512KB) <= L3 cache size < ((L3Size[31:18]+1) * 512KB).
+ return ExtractBitRange(cache_id, 31, 18) * 512;
+ default:
+ return 0;
+ }
+}
+
+#define LEGACY_AMD_MAX_CACHE_LEVEL 4
+
+// https://www.amd.com/system/files/TechDocs/25481.pdf
+// CPUID Fn8000_0005_E[A,B,C,D]X, Fn8000_0006_E[A,B,C,D]X - TLB and Cache info
+static void ParseCacheInfoLegacyAMD(const uint32_t max_ext, CacheInfo* info) {
+ const Leaf cache_tlb_leaf1 = SafeCpuIdEx(max_ext, 0x80000005, 0);
+ const Leaf cache_tlb_leaf2 = SafeCpuIdEx(max_ext, 0x80000006, 0);
+
+ const CacheLevelInfoLegacyAMD legacy_cache_info[LEGACY_AMD_MAX_CACHE_LEVEL] =
+ {(CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf1.ecx,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .level = 1},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf1.edx,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .level = 1},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf2.ecx,
+ .cache_type = CPU_FEATURE_CACHE_UNIFIED,
+ .level = 2},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf2.edx,
+ .cache_type = CPU_FEATURE_CACHE_UNIFIED,
+ .level = 3}};
+
+ const int KiB = 1024;
+ const int UNDEF = -1;
+ for (int i = 0; i < LEGACY_AMD_MAX_CACHE_LEVEL; ++i) {
+ const int level = legacy_cache_info[i].level;
+ const int cache_id = legacy_cache_info[i].cache_id;
+ const CacheType cache_type = legacy_cache_info[i].cache_type;
+ const int cache_size = GetCacheSizeLegacyAMD(level, cache_id);
+ if (cache_size == 0) break;
+ info->levels[i] =
+ (CacheLevelInfo){.level = level,
+ .cache_type = cache_type,
+ .cache_size = cache_size * KiB,
+ .ways = GetWaysLegacyAMD(level, cache_id),
+ .line_size = ExtractBitRange(cache_id, 7, 0),
+ .tlb_entries = UNDEF,
+ .partitioning = UNDEF};
+ ++info->size;
+ }
+}
+
CacheInfo GetX86CacheInfo(void) {
CacheInfo info = kEmptyCacheInfo;
const Leaves leaves = ReadLeaves();
@@ -1674,6 +1903,8 @@ CacheInfo GetX86CacheInfo(void) {
// https://www.amd.com/system/files/TechDocs/25481.pdf
if (IsBitSet(leaves.leaf_80000001.ecx, 22)) {
ParseCacheInfo(leaves.max_cpuid_leaf_ext, 0x8000001D, &info);
+ } else {
+ ParseCacheInfoLegacyAMD(leaves.max_cpuid_leaf_ext, &info);
}
}
return info;
@@ -1710,6 +1941,7 @@ CacheInfo GetX86CacheInfo(void) {
LINE(X86_SSE4_2, sse4_2, , , ) \
LINE(X86_SSE4A, sse4a, , , ) \
LINE(X86_AVX, avx, , , ) \
+ LINE(X86_AVX_VNNI, avx_vnni, , , ) \
LINE(X86_AVX2, avx2, , , ) \
LINE(X86_AVX512F, avx512f, , , ) \
LINE(X86_AVX512CD, avx512cd, , , ) \
@@ -1730,6 +1962,7 @@ CacheInfo GetX86CacheInfo(void) {
LINE(X86_AVX512_4FMAPS, avx512_4fmaps, , , ) \
LINE(X86_AVX512_BF16, avx512_bf16, , , ) \
LINE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, , , ) \
+ LINE(X86_AVX512_FP16, avx512_fp16, , , ) \
LINE(X86_AMX_BF16, amx_bf16, , , ) \
LINE(X86_AMX_TILE, amx_tile, , , ) \
LINE(X86_AMX_INT8, amx_int8, , , ) \
@@ -1743,7 +1976,15 @@ CacheInfo GetX86CacheInfo(void) {
LINE(X86_RDRND, rdrnd, , , ) \
LINE(X86_DCA, dca, , , ) \
LINE(X86_SS, ss, , , ) \
- LINE(X86_ADX, adx, , , )
+ LINE(X86_ADX, adx, , , ) \
+ LINE(X86_LZCNT, lzcnt, , , ) \
+ LINE(X86_GFNI, gfni, , , ) \
+ LINE(X86_MOVDIRI, movdiri, , , ) \
+ LINE(X86_MOVDIR64B, movdir64b, , , ) \
+ 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, , , )
#define INTROSPECTION_PREFIX X86
#define INTROSPECTION_ENUM_PREFIX X86
#include "define_introspection.inl"
@@ -1768,16 +2009,21 @@ CacheInfo GetX86CacheInfo(void) {
LINE(INTEL_HSW) \
LINE(INTEL_BDW) \
LINE(INTEL_SKL) \
+ LINE(INTEL_CCL) \
LINE(INTEL_ATOM_GMT) \
+ LINE(INTEL_ATOM_GMT_PLUS) \
+ LINE(INTEL_ATOM_TMT) \
LINE(INTEL_KBL) \
LINE(INTEL_CFL) \
LINE(INTEL_WHL) \
+ LINE(INTEL_CML) \
LINE(INTEL_CNL) \
LINE(INTEL_ICL) \
LINE(INTEL_TGL) \
LINE(INTEL_SPR) \
LINE(INTEL_ADL) \
LINE(INTEL_RCL) \
+ LINE(INTEL_RPL) \
LINE(INTEL_KNIGHTS_M) \
LINE(INTEL_KNIGHTS_L) \
LINE(INTEL_KNIGHTS_F) \
@@ -1797,7 +2043,8 @@ CacheInfo GetX86CacheInfo(void) {
LINE(AMD_ZEN) \
LINE(AMD_ZEN_PLUS) \
LINE(AMD_ZEN2) \
- LINE(AMD_ZEN3)
+ LINE(AMD_ZEN3) \
+ LINE(AMD_ZEN4)
const char* GetX86MicroarchitectureName(X86Microarchitecture value) {
#define LINE(ENUM) [ENUM] = STRINGIZE(ENUM),
diff --git a/src/impl_x86_windows.c b/src/impl_x86_windows.c
index 0b330d0..8a82823 100644
--- a/src/impl_x86_windows.c
+++ b/src/impl_x86_windows.c
@@ -24,7 +24,7 @@ static void OverrideOsPreserves(OsPreserves* os_preserves) {
// No override
}
-#include <windows.h> // IsProcessorFeaturePresent
+#include "internal/windows_utils.h"
#if defined(CPU_FEATURES_MOCK_CPUID_X86)
extern bool GetWindowsIsProcessorFeaturePresent(DWORD);
@@ -43,15 +43,15 @@ static void DetectFeaturesFromOs(X86Info* info, X86Features* features) {
GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
features->sse3 =
GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
-
-// https://github.com/google/cpu_features/issues/200
-#if (_WIN32_WINNT >= 0x0601) // Win7+
- if (GetX86Microarchitecture(info) == INTEL_WSM) {
- features->ssse3 = true;
- features->sse4_1 = true;
- features->sse4_2 = true;
- }
-#endif
+ features->ssse3 =
+ GetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE);
+ features->sse4_1 =
+ GetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE);
+ features->sse4_2 =
+ GetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE);
+
+// do not bother checking PF_AVX*
+// cause AVX enabled processor will have XCR0 be exposed and this function will be skipped at all
}
#endif // CPU_FEATURES_OS_WINDOWS
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index 0b4eb7a..8226d85 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -35,6 +35,10 @@
#include "cpuinfo_mips.h"
#elif defined(CPU_FEATURES_ARCH_PPC)
#include "cpuinfo_ppc.h"
+#elif defined(CPU_FEATURES_ARCH_S390X)
+#include "cpuinfo_s390x.h"
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+#include "cpuinfo_riscv.h"
#endif
// Design principles
@@ -54,18 +58,18 @@ char gGlobalBuffer[64 * 1024];
BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
.size = sizeof(gGlobalBuffer)};
-static void internal_error() {
+static void internal_error(void) {
fputs("internal error\n", stderr);
exit(EXIT_FAILURE);
}
#define ALIGN 8
-static void assertAligned() {
+static void assertAligned(void) {
if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
}
-static void BA_Align() {
+static void BA_Align(void) {
while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
--gBumpAllocator.size;
++gBumpAllocator.ptr;
@@ -129,10 +133,10 @@ static Node* CreateConstantString(const char* value) {
}
// Adds a map node.
-static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
+static Node* CreateMap(void) { return BA_CreateNode(NT_MAP); }
// Adds an array node.
-static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
+static Node* CreateArray(void) { return BA_CreateNode(NT_ARRAY); }
// Adds a formatted string node.
static Node* CreatePrintfString(const char* format, ...) {
@@ -205,6 +209,12 @@ DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
#elif defined(CPU_FEATURES_ARCH_PPC)
DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
PPC_LAST_)
+#elif defined(CPU_FEATURES_ARCH_S390X)
+DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatures,
+ S390X_LAST_)
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+DEFINE_ADD_FLAGS(GetRiscvFeaturesEnumValue, GetRiscvFeaturesEnumName, RiscvFeatures,
+ RISCV_LAST_)
#endif
// Prints a json string with characters escaping.
@@ -360,15 +370,13 @@ static void AddCacheInfo(Node* root, const CacheInfo* cache_info) {
AddMapEntry(root, "cache_info", array);
}
-static Node* CreateTree() {
+static Node* CreateTree(void) {
Node* root = CreateMap();
#if defined(CPU_FEATURES_ARCH_X86)
- char brand_string[49];
const X86Info info = GetX86Info();
const CacheInfo cache_info = GetX86CacheInfo();
- FillX86BrandString(brand_string);
AddMapEntry(root, "arch", CreateString("x86"));
- AddMapEntry(root, "brand", CreateString(brand_string));
+ AddMapEntry(root, "brand", CreateString(info.brand_string));
AddMapEntry(root, "family", CreateInt(info.family));
AddMapEntry(root, "model", CreateInt(info.model));
AddMapEntry(root, "stepping", CreateInt(info.stepping));
@@ -410,6 +418,20 @@ static Node* CreateTree() {
AddMapEntry(root, "microarchitecture",
CreateString(strings.type.base_platform));
AddFlags(root, &info.features);
+#elif defined(CPU_FEATURES_ARCH_S390X)
+ const S390XInfo info = GetS390XInfo();
+ const S390XPlatformStrings strings = GetS390XPlatformStrings();
+ AddMapEntry(root, "arch", CreateString("s390x"));
+ AddMapEntry(root, "platform", CreateString("zSeries"));
+ AddMapEntry(root, "model", CreateString(strings.type.platform));
+ AddMapEntry(root, "# processors", CreateInt(strings.num_processors));
+ AddFlags(root, &info.features);
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+ const RiscvInfo info = GetRiscvInfo();
+ AddMapEntry(root, "arch", CreateString("risc-v"));
+ AddMapEntry(root, "vendor", CreateString(info.vendor));
+ AddMapEntry(root, "microarchitecture", CreateString(info.uarch));
+ AddFlags(root, &info.features);
#endif
return root;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8e8f72a..f627d74 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -71,7 +71,11 @@ endif()
##------------------------------------------------------------------------------
## cpuinfo_aarch64_test
if(PROCESSOR_IS_AARCH64)
- add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/impl_aarch64_linux_or_android.c)
+ 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)
target_link_libraries(cpuinfo_aarch64_test all_libraries)
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
endif()
@@ -89,3 +93,17 @@ if(PROCESSOR_IS_POWER)
target_link_libraries(cpuinfo_ppc_test all_libraries)
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
endif()
+##------------------------------------------------------------------------------
+## cpuinfo_s390x_test
+if(PROCESSOR_IS_S390X)
+ add_executable(cpuinfo_s390x_test cpuinfo_s390x_test.cc ../src/impl_s390x_linux.c)
+ target_link_libraries(cpuinfo_s390x_test all_libraries)
+ add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test)
+endif()
+##------------------------------------------------------------------------------
+## cpuinfo_riscv_test
+if(PROCESSOR_IS_RISCV)
+ add_executable(cpuinfo_riscv_test cpuinfo_riscv_test.cc ../src/impl_riscv_linux.c)
+ target_link_libraries(cpuinfo_riscv_test all_libraries)
+ add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test)
+endif()
diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc
index 04b6143..ef9abae 100644
--- a/test/cpuinfo_aarch64_test.cc
+++ b/test/cpuinfo_aarch64_test.cc
@@ -14,13 +14,86 @@
#include "cpuinfo_aarch64.h"
+#include <set>
+
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
+#if defined(CPU_FEATURES_OS_WINDOWS)
+#include "internal/windows_utils.h"
+#endif // CPU_FEATURES_OS_WINDOWS
namespace cpu_features {
+class FakeCpuAarch64 {
+ public:
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
+ return windows_isprocessorfeaturepresent_.count(dwProcessorFeature);
+ }
+
+ void SetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
+ windows_isprocessorfeaturepresent_.insert(dwProcessorFeature);
+ }
+
+ WORD GetWindowsNativeSystemInfoProcessorRevision() const {
+ return processor_revision_;
+ }
+
+ void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) {
+ processor_revision_ = wProcessorRevision;
+ }
+
+ private:
+ std::set<DWORD> windows_isprocessorfeaturepresent_;
+ WORD processor_revision_{};
+#endif // CPU_FEATURES_OS_WINDOWS
+};
+
+static FakeCpuAarch64* g_fake_cpu_instance = nullptr;
+
+static FakeCpuAarch64& cpu() {
+ assert(g_fake_cpu_instance != nullptr);
+ return *g_fake_cpu_instance;
+}
+
+#if defined(CPU_FEATURES_OS_WINDOWS)
+extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
+ return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature);
+}
+
+extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() {
+ return cpu().GetWindowsNativeSystemInfoProcessorRevision();
+}
+#endif // CPU_FEATURES_OS_WINDOWS
+
namespace {
+class CpuidAarch64Test : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ assert(g_fake_cpu_instance == nullptr);
+ g_fake_cpu_instance = new FakeCpuAarch64();
+ }
+ void TearDown() override {
+ delete g_fake_cpu_instance;
+ g_fake_cpu_instance = nullptr;
+ }
+};
+
+TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) {
+ const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(AARCH64_FP);
+ i != static_cast<int>(AARCH64_LAST_); ++i) {
+ const auto feature = static_cast<Aarch64FeaturesEnum>(i);
+ const char* name = GetAarch64FeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
+#if defined(CPU_FEATURES_OS_LINUX)
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
TEST(CpuinfoAarch64Test, FromHardwareCap) {
@@ -168,7 +241,36 @@ CPU revision : 3)");
EXPECT_FALSE(info.features.rng);
EXPECT_FALSE(info.features.bti);
EXPECT_FALSE(info.features.mte);
+ EXPECT_FALSE(info.features.ecv);
+ EXPECT_FALSE(info.features.afp);
+ EXPECT_FALSE(info.features.rpres);
+}
+#endif // CPU_FEATURES_OS_LINUX
+
+#if defined(CPU_FEATURES_OS_WINDOWS)
+TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
+ cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(
+ PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
+
+ const auto info = GetAarch64Info();
+
+ EXPECT_EQ(info.revision, 0x03);
+ EXPECT_TRUE(info.features.fp);
+ EXPECT_TRUE(info.features.asimd);
+ EXPECT_TRUE(info.features.crc32);
+ EXPECT_FALSE(info.features.aes);
+ EXPECT_FALSE(info.features.sha1);
+ EXPECT_FALSE(info.features.sha2);
+ EXPECT_FALSE(info.features.pmull);
+ EXPECT_FALSE(info.features.atomics);
+ EXPECT_FALSE(info.features.asimddp);
+ EXPECT_FALSE(info.features.jscvt);
+ EXPECT_FALSE(info.features.lrcpc);
}
+#endif // CPU_FEATURES_OS_WINDOWS
} // namespace
} // namespace cpu_features
diff --git a/test/cpuinfo_arm_test.cc b/test/cpuinfo_arm_test.cc
index ad7f4e8..745b2af 100644
--- a/test/cpuinfo_arm_test.cc
+++ b/test/cpuinfo_arm_test.cc
@@ -21,6 +21,18 @@
namespace cpu_features {
namespace {
+TEST(CpuinfoArmTest, ArmFeaturesEnum) {
+ const char *last_name = GetArmFeaturesEnumName(ARM_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(ARM_SWP); i != static_cast<int>(ARM_LAST_); ++i) {
+ const auto feature = static_cast<ArmFeaturesEnum>(i);
+ const char *name = GetArmFeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
TEST(CpuinfoArmTest, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
diff --git a/test/cpuinfo_mips_test.cc b/test/cpuinfo_mips_test.cc
index a01624a..02ca6c9 100644
--- a/test/cpuinfo_mips_test.cc
+++ b/test/cpuinfo_mips_test.cc
@@ -24,6 +24,18 @@ namespace cpu_features {
namespace {
+TEST(CpuinfoMipsTest, MipsFeaturesEnum) {
+ const char *last_name = GetMipsFeaturesEnumName(MIPS_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(MIPS_MSA); i != static_cast<int>(MIPS_LAST_); ++i) {
+ const auto feature = static_cast<MipsFeaturesEnum>(i);
+ const char *name = GetMipsFeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
TEST(CpuinfoMipsTest, FromHardwareCapBoth) {
ResetHwcaps();
SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0);
@@ -69,6 +81,12 @@ VPE : 0
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_TRUE(info.features.eva);
+ EXPECT_FALSE(info.features.r6);
+ EXPECT_TRUE(info.features.mips16);
+ EXPECT_FALSE(info.features.mdmx);
+ EXPECT_FALSE(info.features.mips3d);
+ EXPECT_FALSE(info.features.smart);
+ EXPECT_TRUE(info.features.dsp);
}
TEST(CpuinfoMipsTest, AR7161) {
@@ -95,6 +113,7 @@ VCEI exceptions : not available
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
+ EXPECT_TRUE(info.features.mips16);
}
TEST(CpuinfoMipsTest, Goldfish) {
@@ -122,5 +141,36 @@ VCEI exceptions : not available
EXPECT_FALSE(info.features.eva);
}
+TEST(CpuinfoMipsTest, BCM1250) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(system type : SiByte BCM91250A (SWARM)
+processor : 0
+cpu model : SiByte SB1 V0.2 FPU V0.2
+BogoMIPS : 532.48
+wait instruction : no
+microsecond timers : yes
+tlb_entries : 64
+extra interrupt vector : yes
+hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
+isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
+ASEs implemented : mdmx mips3d
+shadow register sets : 1
+kscratch registers : 0
+package : 0
+core : 0
+VCED exceptions : not available
+VCEI exceptions : not available
+)");
+ const auto info = GetMipsInfo();
+ EXPECT_FALSE(info.features.msa);
+ EXPECT_FALSE(info.features.eva);
+ EXPECT_FALSE(info.features.mips16);
+ EXPECT_TRUE(info.features.mdmx);
+ EXPECT_TRUE(info.features.mips3d);
+ EXPECT_FALSE(info.features.smart);
+ EXPECT_FALSE(info.features.dsp);
+}
+
} // namespace
} // namespace cpu_features
diff --git a/test/cpuinfo_ppc_test.cc b/test/cpuinfo_ppc_test.cc
index b43a7c8..fc8d288 100644
--- a/test/cpuinfo_ppc_test.cc
+++ b/test/cpuinfo_ppc_test.cc
@@ -22,6 +22,18 @@
namespace cpu_features {
namespace {
+TEST(CpustringsPPCTest, PPCFeaturesEnum) {
+ const char *last_name = GetPPCFeaturesEnumName(PPC_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(PPC_32); i != static_cast<int>(PPC_LAST_); ++i) {
+ const auto feature = static_cast<PPCFeaturesEnum>(i);
+ const char *name = GetPPCFeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
TEST(CpustringsPPCTest, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX,
diff --git a/test/cpuinfo_riscv_test.cc b/test/cpuinfo_riscv_test.cc
new file mode 100644
index 0000000..2ffe2b3
--- /dev/null
+++ b/test/cpuinfo_riscv_test.cc
@@ -0,0 +1,180 @@
+// 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_riscv.h"
+
+#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
+
+namespace cpu_features {
+namespace {
+
+TEST(CpuinfoRiscvTest, Sipeed_Lichee_RV_FromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(processor : 0
+hart : 0
+isa : rv64imafdc
+mmu : sv39
+uarch : thead,c906)");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "c906");
+ EXPECT_STREQ(info.vendor, "thead");
+
+ EXPECT_FALSE(info.features.RV32I);
+ EXPECT_TRUE(info.features.RV64I);
+ EXPECT_TRUE(info.features.M);
+ EXPECT_TRUE(info.features.A);
+ EXPECT_TRUE(info.features.F);
+ EXPECT_TRUE(info.features.D);
+ EXPECT_FALSE(info.features.Q);
+ EXPECT_TRUE(info.features.C);
+ EXPECT_FALSE(info.features.V);
+}
+
+// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/Kendryte-K510-4.17.0.cpuinfo
+TEST(CpuinfoRiscvTest, Kendryte_K510_FromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+hart : 0
+isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
+mmu : sv39
+
+hart : 1
+isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
+mmu : sv39");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "");
+ EXPECT_STREQ(info.vendor, "");
+
+ EXPECT_FALSE(info.features.RV32I);
+ EXPECT_TRUE(info.features.RV64I);
+ EXPECT_TRUE(info.features.M);
+ EXPECT_TRUE(info.features.A);
+ EXPECT_TRUE(info.features.F);
+ EXPECT_TRUE(info.features.D);
+ EXPECT_FALSE(info.features.Q);
+ EXPECT_TRUE(info.features.C);
+ EXPECT_FALSE(info.features.V);
+}
+
+// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/T-Head-C910-5.10.4.cpuinfo
+TEST(CpuinfoRiscvTest, T_Head_C910_FromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+processor : 0
+hart : 0
+isa : rv64imafdcsu
+mmu : sv39
+cpu-freq : 1.2Ghz
+cpu-icache : 64KB
+cpu-dcache : 64KB
+cpu-l2cache : 2MB
+cpu-tlb : 1024 4-ways
+cpu-cacheline : 64Bytes
+cpu-vector : 0.7.1
+
+processor : 1
+hart : 1
+isa : rv64imafdcsu
+mmu : sv39
+cpu-freq : 1.2Ghz
+cpu-icache : 64KB
+cpu-dcache : 64KB
+cpu-l2cache : 2MB
+cpu-tlb : 1024 4-ways
+cpu-cacheline : 64Bytes
+cpu-vector : 0.7.1");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "");
+ EXPECT_STREQ(info.vendor, "");
+
+ EXPECT_FALSE(info.features.RV32I);
+ EXPECT_TRUE(info.features.RV64I);
+ EXPECT_TRUE(info.features.M);
+ EXPECT_TRUE(info.features.A);
+ EXPECT_TRUE(info.features.F);
+ EXPECT_TRUE(info.features.D);
+ EXPECT_FALSE(info.features.Q);
+ EXPECT_TRUE(info.features.C);
+ EXPECT_FALSE(info.features.V);
+}
+
+TEST(CpuinfoRiscvTest, UnknownFromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+processor : 0
+hart : 2
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 1
+hart : 1
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 2
+hart : 3
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 3
+hart : 4
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0)");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "bullet0");
+ EXPECT_STREQ(info.vendor, "sifive");
+
+ EXPECT_FALSE(info.features.RV32I);
+ EXPECT_TRUE(info.features.RV64I);
+ EXPECT_TRUE(info.features.M);
+ EXPECT_TRUE(info.features.A);
+ EXPECT_TRUE(info.features.F);
+ EXPECT_TRUE(info.features.D);
+ EXPECT_FALSE(info.features.Q);
+ EXPECT_TRUE(info.features.C);
+ EXPECT_FALSE(info.features.V);
+}
+
+TEST(CpuinfoRiscvTest, QemuCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+processor : 0
+hart : 0
+isa : rv64imafdcvh_zba_zbb_zbc_zbs
+mmu : sv48)");
+ const auto info = GetRiscvInfo();
+ EXPECT_FALSE(info.features.RV32I);
+ EXPECT_TRUE(info.features.RV64I);
+ EXPECT_TRUE(info.features.M);
+ EXPECT_TRUE(info.features.A);
+ EXPECT_TRUE(info.features.F);
+ EXPECT_TRUE(info.features.D);
+ EXPECT_FALSE(info.features.Q);
+ EXPECT_TRUE(info.features.C);
+ EXPECT_TRUE(info.features.V);
+}
+
+} // namespace
+} // namespace cpu_features
diff --git a/test/cpuinfo_s390x_test.cc b/test/cpuinfo_s390x_test.cc
new file mode 100644
index 0000000..800d3e9
--- /dev/null
+++ b/test/cpuinfo_s390x_test.cc
@@ -0,0 +1,82 @@
+// Copyright 2022 IBM.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpuinfo_s390x.h"
+#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
+
+namespace cpu_features {
+namespace {
+
+TEST(CpustringsS390XTest, S390XFeaturesEnum) {
+ const char *last_name = GetS390XFeaturesEnumName(S390X_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(S390_ZARCH); i != static_cast<int>(S390X_LAST_); ++i) {
+ const auto feature = static_cast<S390XFeaturesEnum>(i);
+ const char *name = GetS390XFeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
+TEST(CpustringsS390XTest, FromHardwareCap) {
+ ResetHwcaps();
+ SetHardwareCapabilities(HWCAP_S390_ESAN3 | HWCAP_S390_HPAGE |
+ HWCAP_S390_NNPA | HWCAP_S390_SIE, 0);
+ GetEmptyFilesystem(); // disabling /proc/cpuinfo
+ const auto info = GetS390XInfo();
+ EXPECT_TRUE(info.features.esan3);
+ EXPECT_TRUE(info.features.edat);
+ EXPECT_TRUE(info.features.nnpa);
+ EXPECT_TRUE(info.features.sie);
+ EXPECT_FALSE(info.features.msa);
+ EXPECT_FALSE(info.features.stfle);
+ EXPECT_FALSE(info.features.vxp2);
+ EXPECT_FALSE(info.features.pcimio);
+}
+
+TEST(CpustringsS390XTest, z16) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo",
+ R"(vendor_id : IBM/S390
+# processors : 24
+bogomips per cpu: 26315.00
+max thread id : 1
+features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt vxp2 nnpa pcimio sie )");
+ SetPlatformPointer("z16");
+ const auto strings = GetS390XPlatformStrings();
+ EXPECT_EQ(strings.num_processors, 24);
+ ASSERT_STREQ(strings.type.platform, "z16");
+}
+
+TEST(CpustringsS390XTest, z15) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo",
+ R"(vendor_id : IBM/S390
+# processors : 2
+bogomips per cpu: 24038.00
+max thread id : 1
+features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt sie)");
+ SetPlatformPointer("z15");
+ const auto strings = GetS390XPlatformStrings();
+ EXPECT_EQ(strings.num_processors, 2);
+ ASSERT_STREQ(strings.type.platform, "z15");
+}
+
+} // namespace
+} // namespace cpu_features
diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc
index 56243b9..de271cc 100644
--- a/test/cpuinfo_x86_test.cc
+++ b/test/cpuinfo_x86_test.cc
@@ -19,8 +19,8 @@
#include <map>
#include <set>
#if defined(CPU_FEATURES_OS_WINDOWS)
-#include <windows.h> // IsProcessorFeaturePresent
-#endif // CPU_FEATURES_OS_WINDOWS
+#include "internal/windows_utils.h"
+#endif // CPU_FEATURES_OS_WINDOWS
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
@@ -118,6 +118,30 @@ class CpuidX86Test : public ::testing::Test {
}
};
+TEST_F(CpuidX86Test, X86MicroarchitectureEnum) {
+ const char *last_name = GetX86MicroarchitectureName(X86_MICROARCHITECTURE_LAST_);
+ EXPECT_STREQ(last_name, "unknown microarchitecture");
+ for (int i = static_cast<int>(X86_UNKNOWN); i != static_cast<int>(X86_MICROARCHITECTURE_LAST_); ++i) {
+ const auto micro = static_cast<X86Microarchitecture>(i);
+ const char *name = GetX86MicroarchitectureName(micro);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
+TEST_F(CpuidX86Test, X86FeaturesEnum) {
+ const char *last_name = GetX86FeaturesEnumName(X86_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(X86_FPU); i != static_cast<int>(X86_LAST_); ++i) {
+ const auto feature = static_cast<X86FeaturesEnum>(i);
+ const char *name = GetX86FeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
TEST_F(CpuidX86Test, SandyBridge) {
cpu().SetOsBackupsExtendedRegisters(true);
cpu().SetLeaves({
@@ -126,7 +150,7 @@ TEST_F(CpuidX86Test, SandyBridge) {
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x02A);
EXPECT_EQ(info.stepping, 0x06);
@@ -188,13 +212,41 @@ TEST_F(CpuidX86Test, SkyLake) {
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x04E);
EXPECT_EQ(info.stepping, 0x03);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
}
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel0050654_SkylakeXeon_CPUID8.txt
+TEST_F(CpuidX86Test, SkyLakeXeon) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00050654, 0x00100800, 0x7FFEFBFF, 0xBFEBFBFF}}
+ });
+ const auto info = GetX86Info();
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x055);
+ EXPECT_EQ(info.stepping, 0x04);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel0050657_CascadeLakeXeon_CPUID.txt
+TEST_F(CpuidX86Test, CascadeLake) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00050657, 0x00400800, 0x7FFEFBFF, 0xBFEBFBFF}}
+ });
+ const auto info = GetX86Info();
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x055);
+ EXPECT_EQ(info.stepping, 0x07);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_CCL);
+}
+
TEST_F(CpuidX86Test, Branding) {
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
@@ -206,9 +258,8 @@ TEST_F(CpuidX86Test, Branding) {
{{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
{{0x80000004, 0}, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}},
});
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
+ const auto info = GetX86Info();
+ EXPECT_STREQ(info.brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
}
TEST_F(CpuidX86Test, KabyLakeCache) {
@@ -228,7 +279,7 @@ TEST_F(CpuidX86Test, KabyLakeCache) {
const auto info = GetX86CacheInfo();
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
- EXPECT_EQ(info.levels[0].cache_type, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[0].ways, 8);
EXPECT_EQ(info.levels[0].line_size, 64);
@@ -236,7 +287,8 @@ TEST_F(CpuidX86Test, KabyLakeCache) {
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
- EXPECT_EQ(info.levels[1].cache_type, 2);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[1].ways, 8);
EXPECT_EQ(info.levels[1].line_size, 64);
@@ -244,7 +296,7 @@ TEST_F(CpuidX86Test, KabyLakeCache) {
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
- EXPECT_EQ(info.levels[2].cache_type, 3);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
EXPECT_EQ(info.levels[2].ways, 4);
EXPECT_EQ(info.levels[2].line_size, 64);
@@ -252,7 +304,7 @@ TEST_F(CpuidX86Test, KabyLakeCache) {
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
- EXPECT_EQ(info.levels[3].cache_type, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
EXPECT_EQ(info.levels[3].ways, 12);
EXPECT_EQ(info.levels[3].line_size, 64);
@@ -277,7 +329,7 @@ TEST_F(CpuidX86Test, HSWCache) {
const auto info = GetX86CacheInfo();
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
- EXPECT_EQ(info.levels[0].cache_type, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[0].ways, 8);
EXPECT_EQ(info.levels[0].line_size, 64);
@@ -285,7 +337,8 @@ TEST_F(CpuidX86Test, HSWCache) {
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
- EXPECT_EQ(info.levels[1].cache_type, 2);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[1].ways, 8);
EXPECT_EQ(info.levels[1].line_size, 64);
@@ -293,7 +346,7 @@ TEST_F(CpuidX86Test, HSWCache) {
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
- EXPECT_EQ(info.levels[2].cache_type, 3);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
EXPECT_EQ(info.levels[2].ways, 8);
EXPECT_EQ(info.levels[2].line_size, 64);
@@ -301,7 +354,7 @@ TEST_F(CpuidX86Test, HSWCache) {
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
- EXPECT_EQ(info.levels[3].cache_type, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
EXPECT_EQ(info.levels[3].ways, 12);
EXPECT_EQ(info.levels[3].line_size, 64);
@@ -319,7 +372,7 @@ TEST_F(CpuidX86Test, AMD_K11_GRIFFIN) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x11);
EXPECT_EQ(info.model, 0x03);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_K11);
@@ -335,7 +388,7 @@ TEST_F(CpuidX86Test, AMD_K12_LLANO) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x12);
EXPECT_EQ(info.model, 0x01);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_K12);
@@ -351,7 +404,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x14);
EXPECT_EQ(info.model, 0x00);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT);
@@ -375,7 +428,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x14);
EXPECT_EQ(info.model, 0x01);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT);
@@ -391,7 +444,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x14);
EXPECT_EQ(info.model, 0x02);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT);
@@ -411,17 +464,13 @@ TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x15);
EXPECT_EQ(info.model, 0x70);
EXPECT_STREQ(info.brand_string,
"AMD A9-9410 RADEON R5, 5 COMPUTE CORES 2C+3G ");
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::AMD_EXCAVATOR);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD A9-9410 RADEON R5, 5 COMPUTE CORES 2C+3G ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt
@@ -438,7 +487,7 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x15);
EXPECT_EQ(info.model, 0x02);
EXPECT_STREQ(info.brand_string,
@@ -446,9 +495,7 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI) {
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::AMD_PILEDRIVER);
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD Opteron(tm) Processor 6376 ");
+ EXPECT_STREQ(info.brand_string, "AMD Opteron(tm) Processor 6376 ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt
@@ -467,7 +514,7 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) {
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
- EXPECT_EQ(info.levels[0].cache_type, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[0].cache_size, 16 * KiB);
EXPECT_EQ(info.levels[0].ways, 4);
EXPECT_EQ(info.levels[0].line_size, 64);
@@ -475,7 +522,8 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) {
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
- EXPECT_EQ(info.levels[1].cache_type, 2);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
EXPECT_EQ(info.levels[1].ways, 2);
EXPECT_EQ(info.levels[1].line_size, 64);
@@ -483,7 +531,7 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) {
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
- EXPECT_EQ(info.levels[2].cache_type, 3);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[2].cache_size, 2 * MiB);
EXPECT_EQ(info.levels[2].ways, 16);
EXPECT_EQ(info.levels[2].line_size, 64);
@@ -491,7 +539,7 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) {
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
- EXPECT_EQ(info.levels[3].cache_type, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
EXPECT_EQ(info.levels[3].ways, 48);
EXPECT_EQ(info.levels[3].line_size, 64);
@@ -499,6 +547,29 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) {
EXPECT_EQ(info.levels[3].partitioning, 1);
}
+// https://github.com/InstLatx64/InstLatx64/blob/master/AuthenticAMD/AuthenticAMD0610F01_K15_Piledriver_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_A10) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00610F01, 0x00040800, 0x3E98320B, 0x178BFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00610F01, 0x20000000, 0x01EBBFFF, 0x2FD3FBFF}},
+ {{0x80000002, 0}, Leaf{0x20444D41, 0x2D303141, 0x30303835, 0x5041204B}},
+ {{0x80000003, 0}, Leaf{0x69772055, 0x52206874, 0x6F656461, 0x6D74286E}},
+ {{0x80000004, 0}, Leaf{0x44482029, 0x61724720, 0x63696870, 0x00202073}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x15);
+ EXPECT_EQ(info.model, 0x10);
+ EXPECT_STREQ(info.brand_string,
+ "AMD A10-5800K APU with Radeon(tm) HD Graphics ");
+ EXPECT_EQ(GetX86Microarchitecture(&info),
+ X86Microarchitecture::AMD_PILEDRIVER);
+}
+
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Interlagos_CPUID3.txt
TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS) {
cpu().SetLeaves({
@@ -513,17 +584,13 @@ TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x15);
EXPECT_EQ(info.model, 0x01);
EXPECT_STREQ(info.brand_string,
"AMD Opteron(TM) Processor 6238 ");
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::AMD_BULLDOZER);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD Opteron(TM) Processor 6238 ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
@@ -541,7 +608,7 @@ TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x15);
EXPECT_EQ(info.model, 0x38);
EXPECT_EQ(info.stepping, 0x01);
@@ -549,10 +616,27 @@ TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI) {
"AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::AMD_STREAMROLLER);
+}
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Zambezi8C_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_ZAMBEZI_ABM) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00600F12, 0x00080800, 0x1E98220B, 0x178BFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00600F12, 0x10000000, 0x01C9BFFF, 0x2FD3FBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x15);
+ EXPECT_EQ(info.model, 0x01);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info),
+ X86Microarchitecture::AMD_BULLDOZER);
+
+ EXPECT_TRUE(info.features.lzcnt);
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0700F01_K16_Kabini_CPUID.txt
@@ -569,16 +653,12 @@ TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x16);
EXPECT_EQ(info.model, 0x00);
EXPECT_STREQ(info.brand_string,
"AMD A4-5000 APU with Radeon(TM) HD Graphics ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_JAGUAR);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD A4-5000 APU with Radeon(TM) HD Graphics ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0730F01_K16_Beema_CPUID2.txt
@@ -595,16 +675,34 @@ TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x16);
EXPECT_EQ(info.model, 0x30);
EXPECT_STREQ(info.brand_string,
"AMD A6-6310 APU with AMD Radeon R4 Graphics ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_PUMA);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/AuthenticAMD/AuthenticAMD0720F61_K16_Cato_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K16_CATO) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00720F61, 0x00080800, 0x3ED8220B, 0x178BFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00720F61, 0x00000000, 0x154837FF, 0x2FD3FBFF}},
+ {{0x80000002, 0}, Leaf{0x20444D41, 0x392D3941, 0x20303238, 0x636F7250}},
+ {{0x80000003, 0}, Leaf{0x6F737365, 0x00000072, 0x00000000, 0x00000000}},
+ {{0x80000004, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ });
+ const auto info = GetX86Info();
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD A6-6310 APU with AMD Radeon R4 Graphics ");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x16);
+ EXPECT_EQ(info.model, 0x26);
+ EXPECT_STREQ(info.brand_string,
+ "AMD A9-9820 Processor");
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_JAGUAR);
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0820F01_K17_Dali_CPUID.txt
@@ -621,16 +719,12 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x17);
EXPECT_EQ(info.model, 0x20);
EXPECT_STREQ(info.brand_string,
"AMD 3020e with Radeon Graphics ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD 3020e with Radeon Graphics ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0800F82_K17_ZenP_CPUID.txt
@@ -647,16 +741,12 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x17);
EXPECT_EQ(info.model, 0x08);
EXPECT_STREQ(info.brand_string,
"AMD Ryzen 7 2700X Eight-Core Processor ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN_PLUS);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD Ryzen 7 2700X Eight-Core Processor ");
}
// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0840F70_K17_CPUID.txt
@@ -673,15 +763,11 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x17);
EXPECT_EQ(info.model, 0x47);
EXPECT_STREQ(info.brand_string, "AMD 4700S 8-Core Processor Desktop Kit");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD 4700S 8-Core Processor Desktop Kit");
}
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt
@@ -698,16 +784,12 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "HygonGenuine");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_HYGON_GENUINE);
EXPECT_EQ(info.family, 0x18);
EXPECT_EQ(info.model, 0x00);
EXPECT_STREQ(info.brand_string,
"Hygon C86 3185 8-core Processor ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN);
-
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "Hygon C86 3185 8-core Processor ");
}
// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID.txt
@@ -726,7 +808,7 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO) {
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
- EXPECT_EQ(info.levels[0].cache_type, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[0].ways, 8);
EXPECT_EQ(info.levels[0].line_size, 64);
@@ -734,7 +816,8 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO) {
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
- EXPECT_EQ(info.levels[1].cache_type, 2);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
EXPECT_EQ(info.levels[1].ways, 4);
EXPECT_EQ(info.levels[1].line_size, 64);
@@ -742,7 +825,7 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO) {
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
- EXPECT_EQ(info.levels[2].cache_type, 3);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[2].cache_size, 512 * KiB);
EXPECT_EQ(info.levels[2].ways, 8);
EXPECT_EQ(info.levels[2].line_size, 64);
@@ -750,7 +833,7 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO) {
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
- EXPECT_EQ(info.levels[3].cache_type, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
EXPECT_EQ(info.levels[3].cache_size, 8 * MiB);
EXPECT_EQ(info.levels[3].ways, 16);
EXPECT_EQ(info.levels[3].line_size, 64);
@@ -772,16 +855,342 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "AuthenticAMD");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
EXPECT_EQ(info.family, 0x19);
EXPECT_EQ(info.model, 0x21);
EXPECT_STREQ(info.brand_string,
"AMD Ryzen 9 5900X 12-Core Processor ");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN3);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A40F41_K19_Rembrandt_03_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K19_ZEN3) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00A40F41, 0x00100800, 0x7EF8320B, 0x178BFBFF}},
+ {{0x80000000, 0}, Leaf{0x80000023, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00A40F41, 0x50000000, 0x75C237FF, 0x2FD3FBFF}},
+ {{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2039206E, 0x30303936}},
+ {{0x80000003, 0}, Leaf{0x77205848, 0x20687469, 0x65646152, 0x47206E6F}},
+ {{0x80000004, 0}, Leaf{0x68706172, 0x20736369, 0x20202020, 0x00202020}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x19);
+ EXPECT_EQ(info.model, 0x44);
+ EXPECT_STREQ(info.brand_string,
+ "AMD Ryzen 9 6900HX with Radeon Graphics ");
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN3);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A60F12_K19_Raphael_01_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K19_ZEN4_RAPHAEL) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x00A60F12, 0x000C0800, 0x7EF8320B, 0x178BFBFF}},
+ {{0x80000000, 0}, Leaf{0x80000028, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00A60F12, 0x00000000, 0x75C237FF, 0x2FD3FBFF}},
+ {{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2035206E, 0x30303637}},
+ {{0x80000003, 0}, Leaf{0x2D362058, 0x65726F43, 0x6F725020, 0x73736563}},
+ {{0x80000004, 0}, Leaf{0x2020726F, 0x20202020, 0x20202020, 0x00202020}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(info.family, 0x19);
+ EXPECT_EQ(info.model, 0x61);
+ EXPECT_STREQ(info.brand_string,
+ "AMD Ryzen 5 7600X 6-Core Processor ");
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN4);
+}
+
+// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F11_Hygon_01_CPUID.txt
+TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_OCTAL_CORE_C86_3250) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}},
+ {{0x00000001, 0}, Leaf{0x00900F11, 0x00100800, 0x76D8320B, 0x178BFBFF}},
+ {{0x80000000, 0}, Leaf{0x8000001F, 0x6F677948, 0x656E6975, 0x6E65476E}},
+ {{0x80000001, 0}, Leaf{0x00900F11, 0x60000000, 0x35C233FF, 0x2FD3FBFF}},
+ {{0x80000002, 0}, Leaf{0x6F677948, 0x3843206E, 0x32332036, 0x20203035}},
+ {{0x80000003, 0}, Leaf{0x6F632D38, 0x50206572, 0x65636F72, 0x726F7373}},
+ {{0x80000004, 0}, Leaf{0x20202020, 0x20202020, 0x20202020, 0x00202020}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_EQ(info.model, 0x01);
+ EXPECT_EQ(info.family, 0x18);
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_HYGON_GENUINE);
+ EXPECT_STREQ(info.brand_string,
+ "Hygon C86 3250 8-core Processor ");
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD08A0F00_K17_Mendocino_01_CPUID.txt
+TEST_F(CpuidX86Test, AMD_ZEN2_MENDOCINO) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x00000001, 0}, Leaf{0x008A0F00, 0x00080800, 0x7EF8320B, 0x178BFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_EQ(info.model, 0xA0);
+ EXPECT_EQ(info.family, 0x17);
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00906A4_AlderLakeP_00_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_AVX_VNNI) {
+ cpu().SetOsBackupsExtendedRegisters(true);
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000906A4, 0x00400800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000001, 0x239CA7EB, 0x984007AC, 0xFC18C410}},
+ {{0x00000007, 1}, Leaf{0x00400810, 0x00000000, 0x00000000, 0x00000000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x9A);
+ EXPECT_TRUE(info.features.avx_vnni);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0090672_AlderLake_BC_AVX512_CPUID01.txt
+TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_AVX512) {
+ cpu().SetOsBackupsExtendedRegisters(true);
+#if defined(CPU_FEATURES_OS_MACOS)
+ cpu().SetDarwinSysCtlByName("hw.optional.avx512f");
+#endif
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000906A4, 0x00400800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000001, 0xF3BFA7EB, 0x98C07FEE, 0xFC9CC510}},
+ {{0x00000007, 1}, Leaf{0x00401C30, 0x00000000, 0x00000000, 0x00000000}},
+ });
+
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x9A);
+ EXPECT_TRUE(info.features.avx512f);
+ EXPECT_TRUE(info.features.avx512bw);
+ EXPECT_TRUE(info.features.avx512dq);
+ EXPECT_TRUE(info.features.avx512cd);
+ EXPECT_TRUE(info.features.avx512vl);
+ EXPECT_TRUE(info.features.avx512_vp2intersect);
+ EXPECT_TRUE(info.features.avx512vbmi);
+ EXPECT_TRUE(info.features.avx512vbmi2);
+ EXPECT_TRUE(info.features.avx512bitalg);
+ EXPECT_TRUE(info.features.avx512vpopcntdq);
+ EXPECT_TRUE(info.features.avx512ifma);
+ EXPECT_TRUE(info.features.avx512_bf16);
+ EXPECT_TRUE(info.features.avx512_fp16);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00806C1_TigerLake_CPUID3.txt
+TEST_F(CpuidX86Test, INTEL_TIGER_LAKE_AVX512) {
+ cpu().SetOsBackupsExtendedRegisters(true);
+#if defined(CPU_FEATURES_OS_MACOS)
+ cpu().SetDarwinSysCtlByName("hw.optional.avx512f");
+#endif
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000806C1, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0xF3BFA7EB, 0x18C05FCE, 0xFC100510}},
+ });
+
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x8C);
+ EXPECT_TRUE(info.features.avx512f);
+ EXPECT_TRUE(info.features.avx512bw);
+ EXPECT_TRUE(info.features.avx512dq);
+ EXPECT_TRUE(info.features.avx512cd);
+ EXPECT_TRUE(info.features.avx512vl);
+ EXPECT_TRUE(info.features.avx512_vp2intersect);
+ EXPECT_TRUE(info.features.avx512vbmi);
+ EXPECT_TRUE(info.features.avx512vbmi2);
+ EXPECT_TRUE(info.features.avx512bitalg);
+ EXPECT_TRUE(info.features.avx512vpopcntdq);
+ EXPECT_TRUE(info.features.avx512ifma);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_TGL);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00706E5_IceLakeY_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_ICE_LAKE_GFNI) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000706E5, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0xF2BF27EF, 0x40405F4E, 0xBC000410}},
+ });
+
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x7E);
+ EXPECT_TRUE(info.features.gfni);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ICL);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00906C0_JasperLake_CPUID01.txt
+TEST_F(CpuidX86Test, INTEL_TREMONT_JASPER_LAKE_MOVDR) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00090661, 0x00800800, 0x4FF8EBBF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x2394A2C3, 0x18400124, 0xFC000400}},
+ });
+
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x96);
+ EXPECT_TRUE(info.features.movdiri);
+ EXPECT_TRUE(info.features.movdir64b);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ATOM_TMT);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel0090672_AlderLake_LC_BC_CPUID01.txt
+TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_REP) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00090672, 0x00800800, 0x7FFAFBFF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000001, 0x239CA7EB, 0x98C027AC, 0xFC1CC410}},
+ {{0x00000007, 1}, Leaf{0x00400810, 0x00000000, 0x00000000, 0x00000000}},
+ });
+
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x97);
+ EXPECT_TRUE(info.features.erms);
+ EXPECT_TRUE(info.features.fs_rep_mov);
+ EXPECT_FALSE(info.features.fz_rep_movsb);
+ EXPECT_TRUE(info.features.fs_rep_stosb);
+ EXPECT_FALSE(info.features.fs_rep_cmpsb_scasb);
+
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0100FA0_K10_Thuban_CPUID.txt
+TEST_F(CpuidX86Test, AMD_THUBAN_CACHE_INFO) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00100FA0, 0x10000050, 0x000037FF, 0xEFD3FBFF}},
+ {{0x80000005, 0}, Leaf{0xFF30FF10, 0xFF30FF20, 0x40020140, 0x40020140}},
+ {{0x80000006, 0}, Leaf{0x20800000, 0x42004200, 0x02008140, 0x0030B140}},
+ });
+ const auto info = GetX86CacheInfo();
+
+ EXPECT_EQ(info.size, 4);
+ EXPECT_EQ(info.levels[0].level, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
+ EXPECT_EQ(info.levels[0].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[0].ways, 2);
+ EXPECT_EQ(info.levels[0].line_size, 64);
+
+ EXPECT_EQ(info.levels[1].level, 1);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
+ EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[1].ways, 2);
+ EXPECT_EQ(info.levels[1].line_size, 64);
+
+ EXPECT_EQ(info.levels[2].level, 2);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
+ EXPECT_EQ(info.levels[2].cache_size, 512 * KiB);
+ EXPECT_EQ(info.levels[2].ways, 16);
+ EXPECT_EQ(info.levels[2].line_size, 64);
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "AMD Ryzen 9 5900X 12-Core Processor ");
+ EXPECT_EQ(info.levels[3].level, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
+ EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
+ EXPECT_EQ(info.levels[3].ways, 48);
+ EXPECT_EQ(info.levels[3].line_size, 64);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0020FB1_K8_Manchester_CPUID.txt
+TEST_F(CpuidX86Test, AMD_MANCHESTER_CACHE_INFO) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000001, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000000, 0}, Leaf{0x80000018, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00020FB1, 0x00000150, 0x00000003, 0xE3D3FBFF}},
+ {{0x80000005, 0}, Leaf{0xFF08FF08, 0xFF20FF20, 0x40020140, 0x40020140}},
+ {{0x80000006, 0}, Leaf{0x00000000, 0x42004200, 0x02008140, 0x00000000}},
+ });
+ const auto info = GetX86CacheInfo();
+
+ EXPECT_EQ(info.size, 3);
+ EXPECT_EQ(info.levels[0].level, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
+ EXPECT_EQ(info.levels[0].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[0].ways, 2);
+ EXPECT_EQ(info.levels[0].line_size, 64);
+
+ EXPECT_EQ(info.levels[1].level, 1);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
+ EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[1].ways, 2);
+ EXPECT_EQ(info.levels[1].line_size, 64);
+
+ EXPECT_EQ(info.levels[2].level, 2);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
+ EXPECT_EQ(info.levels[2].cache_size, 512 * KiB);
+ EXPECT_EQ(info.levels[2].ways, 16);
+ EXPECT_EQ(info.levels[2].line_size, 64);
+}
+
+// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0100F22_K10_Agena_CPUID.txt
+TEST_F(CpuidX86Test, AMD_AGENA_CACHE_INFO) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000005, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000000, 0}, Leaf{0x8000001A, 0x68747541, 0x444D4163, 0x69746E65}},
+ {{0x80000001, 0}, Leaf{0x00100F22, 0x10000000, 0x000007FF, 0xEFD3FBFF}},
+ {{0x80000005, 0}, Leaf{0xFF30FF10, 0xFF30FF20, 0x40020140, 0x40020140}},
+ {{0x80000006, 0}, Leaf{0x20800000, 0x42004200, 0x02008140, 0x0010A140}},
+ });
+ const auto info = GetX86CacheInfo();
+
+ EXPECT_EQ(info.size, 4);
+ EXPECT_EQ(info.levels[0].level, 1);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
+ EXPECT_EQ(info.levels[0].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[0].ways, 2);
+ EXPECT_EQ(info.levels[0].line_size, 64);
+
+ EXPECT_EQ(info.levels[1].level, 1);
+ EXPECT_EQ(info.levels[1].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
+ EXPECT_EQ(info.levels[1].cache_size, 64 * KiB);
+ EXPECT_EQ(info.levels[1].ways, 2);
+ EXPECT_EQ(info.levels[1].line_size, 64);
+
+ EXPECT_EQ(info.levels[2].level, 2);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
+ EXPECT_EQ(info.levels[2].cache_size, 512 * KiB);
+ EXPECT_EQ(info.levels[2].ways, 16);
+ EXPECT_EQ(info.levels[2].line_size, 64);
+
+ EXPECT_EQ(info.levels[3].level, 3);
+ EXPECT_EQ(info.levels[3].cache_type, CacheType::CPU_FEATURE_CACHE_UNIFIED);
+ EXPECT_EQ(info.levels[3].cache_size, 2 * MiB);
+ EXPECT_EQ(info.levels[3].ways, 32);
+ EXPECT_EQ(info.levels[3].line_size, 64);
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt
@@ -792,6 +1201,9 @@ TEST_F(CpuidX86Test, Nehalem) {
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE);
#elif defined(CPU_FEATURES_OS_MACOS)
cpu().SetDarwinSysCtlByName("hw.optional.sse");
cpu().SetDarwinSysCtlByName("hw.optional.sse2");
@@ -844,7 +1256,7 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x1A);
EXPECT_EQ(info.stepping, 0x02);
@@ -852,20 +1264,12 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2
"Genuine Intel(R) CPU @ 0000 @ 1.87GHz");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM);
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU @ 0000 @ 1.87GHz");
-
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
-#if !defined(CPU_FEATURES_OS_WINDOWS)
- // Currently disabled on Windows as IsProcessorFeaturePresent do not support
- // feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
-#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
@@ -876,6 +1280,9 @@ TEST_F(CpuidX86Test, Atom) {
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE);
#elif defined(CPU_FEATURES_OS_MACOS)
cpu().SetDarwinSysCtlByName("hw.optional.sse");
cpu().SetDarwinSysCtlByName("hw.optional.sse2");
@@ -927,7 +1334,7 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x37);
EXPECT_EQ(info.stepping, 0x03);
@@ -936,20 +1343,12 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_ATOM_SMT);
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, " Intel(R) Celeron(R) CPU J1900 @ 1.99GHz");
-
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
-#if !defined(CPU_FEATURES_OS_WINDOWS)
- // Currently disabled on Windows as IsProcessorFeaturePresent do not support
- // feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
-#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}
// https://www.felixcloutier.com/x86/cpuid#example-3-1--example-of-cache-and-tlb-interpretation
@@ -964,7 +1363,7 @@ TEST_F(CpuidX86Test, P4_CacheInfo) {
EXPECT_EQ(info.size, 5);
EXPECT_EQ(info.levels[0].level, UNDEF);
- EXPECT_EQ(info.levels[0].cache_type, CPU_FEATURE_CACHE_TLB);
+ EXPECT_EQ(info.levels[0].cache_type, CacheType::CPU_FEATURE_CACHE_TLB);
EXPECT_EQ(info.levels[0].cache_size, 4 * KiB);
EXPECT_EQ(info.levels[0].ways, UNDEF);
EXPECT_EQ(info.levels[0].line_size, UNDEF);
@@ -972,7 +1371,7 @@ TEST_F(CpuidX86Test, P4_CacheInfo) {
EXPECT_EQ(info.levels[0].partitioning, 0);
EXPECT_EQ(info.levels[1].level, UNDEF);
- EXPECT_EQ(info.levels[1].cache_type, CPU_FEATURE_CACHE_TLB);
+ EXPECT_EQ(info.levels[1].cache_type, CacheType::CPU_FEATURE_CACHE_TLB);
EXPECT_EQ(info.levels[1].cache_size, 4 * KiB);
EXPECT_EQ(info.levels[1].ways, UNDEF);
EXPECT_EQ(info.levels[1].line_size, UNDEF);
@@ -980,7 +1379,7 @@ TEST_F(CpuidX86Test, P4_CacheInfo) {
EXPECT_EQ(info.levels[1].partitioning, 0);
EXPECT_EQ(info.levels[2].level, 1);
- EXPECT_EQ(info.levels[2].cache_type, CPU_FEATURE_CACHE_DATA);
+ EXPECT_EQ(info.levels[2].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[2].cache_size, 8 * KiB);
EXPECT_EQ(info.levels[2].ways, 4);
EXPECT_EQ(info.levels[2].line_size, 64);
@@ -988,7 +1387,8 @@ TEST_F(CpuidX86Test, P4_CacheInfo) {
EXPECT_EQ(info.levels[2].partitioning, 0);
EXPECT_EQ(info.levels[3].level, 1);
- EXPECT_EQ(info.levels[3].cache_type, CPU_FEATURE_CACHE_INSTRUCTION);
+ EXPECT_EQ(info.levels[3].cache_type,
+ CacheType::CPU_FEATURE_CACHE_INSTRUCTION);
EXPECT_EQ(info.levels[3].cache_size, 12 * KiB);
EXPECT_EQ(info.levels[3].ways, 8);
EXPECT_EQ(info.levels[3].line_size, UNDEF);
@@ -996,7 +1396,7 @@ TEST_F(CpuidX86Test, P4_CacheInfo) {
EXPECT_EQ(info.levels[3].partitioning, 0);
EXPECT_EQ(info.levels[4].level, 2);
- EXPECT_EQ(info.levels[4].cache_type, CPU_FEATURE_CACHE_DATA);
+ EXPECT_EQ(info.levels[4].cache_type, CacheType::CPU_FEATURE_CACHE_DATA);
EXPECT_EQ(info.levels[4].cache_size, 256 * KiB);
EXPECT_EQ(info.levels[4].ways, 8);
EXPECT_EQ(info.levels[4].line_size, 64);
@@ -1035,28 +1435,20 @@ flags : fpu mmx sse
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x07);
EXPECT_EQ(info.stepping, 0x03);
EXPECT_STREQ(info.brand_string, "");
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN);
- char brand_string[49];
- FillX86BrandString(brand_string);
- EXPECT_STREQ(brand_string, "");
-
EXPECT_TRUE(info.features.mmx);
EXPECT_TRUE(info.features.sse);
EXPECT_FALSE(info.features.sse2);
EXPECT_FALSE(info.features.sse3);
-#if !defined(CPU_FEATURES_OS_WINDOWS)
- // Currently disabled on Windows as IsProcessorFeaturePresent do not support
- // feature detection > sse3.
EXPECT_FALSE(info.features.ssse3);
EXPECT_FALSE(info.features.sse4_1);
EXPECT_FALSE(info.features.sse4_2);
-#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000480_486_CPUID.txt
@@ -1067,7 +1459,7 @@ TEST_F(CpuidX86Test, INTEL_80486) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x04);
EXPECT_EQ(info.model, 0x08);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_80486);
@@ -1081,7 +1473,7 @@ TEST_F(CpuidX86Test, INTEL_P54C) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x05);
EXPECT_EQ(info.model, 0x02);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_P5);
@@ -1095,13 +1487,42 @@ TEST_F(CpuidX86Test, INTEL_LAKEMONT) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x05);
EXPECT_EQ(info.model, 0x09);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_LAKEMONT);
}
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00006E8_PM_Yonah_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_CORE_YONAH) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000A, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000006E8, 0x00010800, 0x0000C109, 0xAFE9FBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x0E);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_CORE);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00706A8_GoldmontPlus_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_GOLDMONT_PLUS) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000018, 0x756E6547, 0x6c65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000706A8, 0x00400800, 0x4FF8EBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x7A);
+ EXPECT_EQ(GetX86Microarchitecture(&info),
+ X86Microarchitecture::INTEL_ATOM_GMT_PLUS);
+}
+
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0050670_KnightsLanding_CPUID.txt
TEST_F(CpuidX86Test, INTEL_KNIGHTS_LANDING) {
cpu().SetLeaves({
@@ -1110,17 +1531,177 @@ TEST_F(CpuidX86Test, INTEL_KNIGHTS_LANDING) {
});
const auto info = GetX86Info();
- EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x57);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_KNIGHTS_L);
}
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00806EC_CometLake_CPUID2.txt
+TEST_F(CpuidX86Test, INTEL_CML_U) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000806EC, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x8E);
+ EXPECT_EQ(info.stepping, 0x0C);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_CML);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00A0652_CometLake_CPUID1.txt
+TEST_F(CpuidX86Test, INTEL_CML_H) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000A0652, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0xA5);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_CML);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00A0660_CometLake_CPUID1.txt
+TEST_F(CpuidX86Test, INTEL_CML_U2) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000A0660, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0xA6);
+ EXPECT_EQ(info.stepping, 0x00);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_CML);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00806A1_Lakefield_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_ATOM_TMT_LAKEFIELD) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000806A1, 0x00100800, 0x4FD8EBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x8A);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ATOM_TMT);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0090661_ElkhartLake_CPUID01.txt
+TEST_F(CpuidX86Test, INTEL_ATOM_TMT_ELKHART_LAKE) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00090661, 0x00800800, 0x4FF8EBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x96);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ATOM_TMT);
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00906C0_JasperLake_01_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_ATOM_TMT_JASPER_LAKE) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000001B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000906C0, 0x00800800, 0x4FF8EBBF, 0xBFEBFBFF}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x9C);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ATOM_TMT);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B0671_RaptorLake_02_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000B0671, 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, 0xB7);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00306F2_HaswellEP2_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_HASWELL_LZCNT) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000F, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000306F2, 0x00200800, 0x7FFEFBFF, 0xBFEBFBFF}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x000037AB, 0x00000000, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000021, 0x2C100000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x3F);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_HSW);
+
+ EXPECT_TRUE(info.features.lzcnt);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06A2_RaptorLakeP_03_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_P) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000B06A3, 0x00400800, 0x7FFAFBFF, 0xBFEBFBFF}},
+ {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0xBA);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL);
+}
+
+// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06F2_RaptorLakeS_02_CPUID.txt
+TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_S) {
+ cpu().SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000B06F2, 0x00800800, 0x7FFAFBFF, 0xBFEBFBFF}},
+ {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL);
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0xBF);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL);
+}
+
// https://github.com/google/cpu_features/issues/200
// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt
#if defined(CPU_FEATURES_OS_WINDOWS)
TEST_F(CpuidX86Test, WIN_INTEL_WESTMERE_EX) {
+ // Pre AVX cpus don't have xsave
+ cpu().SetOsBackupsExtendedRegisters(false);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE);
+ cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE);
+
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000206F2, 0x00400800, 0x02BEE3FF, 0xBFEBFBFF}},
@@ -1131,15 +1712,12 @@ TEST_F(CpuidX86Test, WIN_INTEL_WESTMERE_EX) {
EXPECT_EQ(info.model, 0x2F);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_WSM);
-#if (_WIN32_WINNT < 0x0601) // before Win7
- EXPECT_FALSE(info.features.ssse3);
- EXPECT_FALSE(info.features.sse4_1);
- EXPECT_FALSE(info.features.sse4_2);
-#else
+ EXPECT_TRUE(info.features.sse);
+ EXPECT_TRUE(info.features.sse2);
+ EXPECT_TRUE(info.features.sse3);
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
-#endif
}
#endif // CPU_FEATURES_OS_WINDOWS