aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Levillain <rpl@google.com>2020-10-15 17:46:27 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-10-15 17:46:27 +0000
commit607db9b85105297574b0cb84da1ebda7f2c0c3ee (patch)
treeaad9356ab58e4885f8393de3ce23f744194af8b0
parent1e0cc1fb030178ec0a3d61427ed621f858969915 (diff)
parent1fb67bca22774bfb5cb19d5195052efc37c63c28 (diff)
downloadcpu_features-607db9b85105297574b0cb84da1ebda7f2c0c3ee.tar.gz
Merge v0.6.0 into master. am: 1fb67bca22
Original change: https://android-review.googlesource.com/c/platform/external/cpu_features/+/1460885 Change-Id: I0fa9c30b0901a9f38042a46000542c28ef919950
-rw-r--r--.github/workflows/Dockerfile5
-rw-r--r--.github/workflows/clang_format.yml24
-rw-r--r--Android.bp30
-rw-r--r--CMakeLists.txt17
-rw-r--r--METADATA6
-rw-r--r--README.md4
-rw-r--r--TEST_MAPPING7
-rw-r--r--include/cpu_features_cache_info.h2
-rw-r--r--include/cpu_features_macros.h6
-rw-r--r--include/cpuinfo_aarch64.h104
-rw-r--r--include/cpuinfo_arm.h38
-rw-r--r--include/cpuinfo_mips.h4
-rw-r--r--include/cpuinfo_ppc.h2
-rw-r--r--include/cpuinfo_x86.h2
-rw-r--r--include/internal/bit_utils.h3
-rw-r--r--include/internal/cpuid_x86.h5
-rw-r--r--include/internal/filesystem.h3
-rw-r--r--include/internal/hwcaps.h6
-rw-r--r--include/internal/stack_line_reader.h2
-rw-r--r--include/internal/string_view.h3
-rw-r--r--include/internal/unix_features_aggregator.h72
-rw-r--r--ndk_compat/cpu-features.c5
-rw-r--r--ndk_compat/ndk-compat-test.c1
-rw-r--r--src/cpuinfo_aarch64.c196
-rw-r--r--src/cpuinfo_arm.c128
-rw-r--r--src/cpuinfo_mips.c52
-rw-r--r--src/cpuinfo_ppc.c164
-rw-r--r--src/cpuinfo_x86.c482
-rw-r--r--src/define_tables.h67
-rw-r--r--src/filesystem.c2
-rw-r--r--src/hwcaps.c46
-rw-r--r--src/stack_line_reader.c5
-rw-r--r--src/string_view.c2
-rw-r--r--src/unix_features_aggregator.c52
-rw-r--r--src/utils/list_cpu_features.c4
-rw-r--r--test/CMakeLists.txt11
-rw-r--r--test/bit_utils_test.cc2
-rw-r--r--test/cpuinfo_aarch64_test.cc9
-rw-r--r--test/cpuinfo_arm_test.cc6
-rw-r--r--test/cpuinfo_mips_test.cc6
-rw-r--r--test/cpuinfo_ppc_test.cc4
-rw-r--r--test/cpuinfo_x86_test.cc280
-rw-r--r--test/filesystem_for_testing.cc2
-rw-r--r--test/filesystem_for_testing.h2
-rw-r--r--test/hwcaps_for_testing.cc5
-rw-r--r--test/hwcaps_for_testing.h2
-rw-r--r--test/stack_line_reader_test.cc4
-rw-r--r--test/string_view_test.cc10
-rw-r--r--test/unix_features_aggregator_test.cc110
49 files changed, 978 insertions, 1026 deletions
diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile
new file mode 100644
index 0000000..41dfc93
--- /dev/null
+++ b/.github/workflows/Dockerfile
@@ -0,0 +1,5 @@
+# Create a virtual environment with all tools installed
+# ref: https://hub.docker.com/_/alpine
+FROM alpine:edge
+# Install system build dependencies
+RUN apk add --no-cache git clang
diff --git a/.github/workflows/clang_format.yml b/.github/workflows/clang_format.yml
new file mode 100644
index 0000000..17d1567
--- /dev/null
+++ b/.github/workflows/clang_format.yml
@@ -0,0 +1,24 @@
+name: clang-format Check
+
+on: [push, pull_request]
+
+jobs:
+ # Building using the github runner environement directly.
+ clang-format:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Fetch origin/master
+ run: git fetch origin master
+ - name: List of changed file(s)
+ run: git diff --name-only FETCH_HEAD
+
+ - name: Build clang-format docker
+ run: cd .github/workflows && docker build --tag=linter .
+ - name: Check clang-format
+ run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --version
+ - name: clang-format help
+ run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --help
+
+ - name: Check current commit
+ run: docker run --rm --init -v $(pwd):/repo -w /repo linter:latest sh -c "git diff --diff-filter=d --name-only FETCH_HEAD | grep '\.c$\|\.h$\|\.cc$' | xargs clang-format --style=file --dry-run --Werror "
diff --git a/Android.bp b/Android.bp
index df66e37..a6d18b2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -34,11 +34,10 @@ cc_library {
}
cc_library {
- name: "libcpu_features-unix_based_hardware_detection",
+ name: "libcpu_features-hwcaps",
defaults: ["cpu_features-defaults"],
srcs: [
"src/hwcaps.c",
- "src/unix_features_aggregator.c",
],
cflags: [
"-DHAVE_DLFCN_H",
@@ -74,7 +73,7 @@ cc_library {
"src/cpuinfo_arm.c",
],
whole_static_libs: [
- "libcpu_features-unix_based_hardware_detection",
+ "libcpu_features-hwcaps",
],
},
arm64: {
@@ -82,7 +81,7 @@ cc_library {
"src/cpuinfo_aarch64.c",
],
whole_static_libs: [
- "libcpu_features-unix_based_hardware_detection",
+ "libcpu_features-hwcaps",
],
cflags: [
"-Wno-gnu-designator",
@@ -186,8 +185,10 @@ cc_test_library {
defaults: ["cpu_features-test-defaults"],
cflags: [
"-DCPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL",
+ "-DCPU_FEATURES_TEST",
],
srcs: [
+ "src/hwcaps.c",
"test/hwcaps_for_testing.cc",
],
static_libs: [
@@ -239,9 +240,6 @@ cc_test_library {
"cpu_features-test-defaults",
"stack_line_reader-defaults",
],
- srcs: [
- "src/unix_features_aggregator.c",
- ],
whole_static_libs: [
"libcpu_features-filesystem_for_testing",
"libcpu_features-hwcaps_for_testing",
@@ -290,17 +288,6 @@ cc_test {
}
cc_test {
- name: "cpu_features-unix_features_aggregator_test",
- defaults: ["cpu_features-test-defaults"],
- srcs: [
- "test/unix_features_aggregator_test.cc",
- ],
- static_libs: [
- "libcpu_features-all_libraries",
- ],
-}
-
-cc_test {
name: "cpu_features-cpuinfo_test",
defaults: [
"cpu_features-test-defaults",
@@ -308,6 +295,9 @@ cc_test {
static_libs: [
"libcpu_features-all_libraries",
],
+ cflags: [
+ "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
+ ],
arch: {
x86: {
cflags: [
@@ -330,9 +320,6 @@ cc_test {
],
},
arm: {
- cflags: [
- "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
- ],
srcs: [
"test/cpuinfo_arm_test.cc",
"src/cpuinfo_arm.c",
@@ -340,7 +327,6 @@ cc_test {
},
arm64: {
cflags: [
- "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
"-Wno-gnu-designator",
],
srcs: [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 85102c7..f9daeac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
-project(CpuFeatures VERSION 0.5.0 LANGUAGES C)
+project(CpuFeatures VERSION 0.6.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
@@ -22,8 +22,8 @@ endif(NOT CMAKE_BUILD_TYPE)
option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
# it prominent in the GUI.
-# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
-# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
+# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
+# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
# Prefer static linking from source whenever possible.
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
# PIC
@@ -114,9 +114,7 @@ setup_include_and_definitions(utils)
if(UNIX)
add_library(unix_based_hardware_detection OBJECT
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
- ${PROJECT_SOURCE_DIR}/include/internal/unix_features_aggregator.h
${PROJECT_SOURCE_DIR}/src/hwcaps.c
- ${PROJECT_SOURCE_DIR}/src/unix_features_aggregator.c
)
setup_include_and_definitions(unix_based_hardware_detection)
check_include_file(dlfcn.h HAVE_DLFCN_H)
@@ -148,6 +146,11 @@ set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}
target_include_directories(cpu_features
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
)
+if(PROCESSOR_IS_X86)
+ if(APPLE)
+ target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
+ endif()
+endif()
add_library(CpuFeature::cpu_features ALIAS cpu_features)
#
@@ -175,11 +178,11 @@ if(BUILD_TESTING)
# Automatically incorporate googletest into the CMake Project if target not
# found.
enable_language(CXX)
-
+
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
-
+
if(NOT TARGET gtest OR NOT TARGET gmock_main)
# Download and unpack googletest at configure time.
configure_file(
diff --git a/METADATA b/METADATA
index 728702c..5e2b871 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/cpu_features.git"
}
- version: "v0.5.0"
+ version: "v0.6.0"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 9
- day: 22
+ month: 10
+ day: 15
}
}
diff --git a/README.md b/README.md
index cbd115a..8a34168 100644
--- a/README.md
+++ b/README.md
@@ -121,7 +121,6 @@ This feature is currently available only for x86 microarchitectures.
### Running sample code
Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
-.
```shell
% ./build/list_cpu_features
@@ -185,7 +184,7 @@ Please check the [CMake build instructions](cmake/README.md).
<a name="quickstart"></a>
### Quickstart with `Ninja`
- - build `list_cpu_features`
+ - build `list_cpu_features`
```
cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release
ninja -C/tmp/cpu_features
@@ -197,5 +196,4 @@ Please check the [CMake build instructions](cmake/README.md).
cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON
ninja -C/tmp/cpu_features
ninja -C/tmp/cpu_features test
-
```
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 0af6ef9..824f432 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -22,13 +22,6 @@
"name": "cpu_features-stack_line_reader_test"
},
{
- "name": "cpu_features-unix_features_aggregator_test",
- "host": true
- },
- {
- "name": "cpu_features-unix_features_aggregator_test"
- },
- {
"name": "cpu_features-cpuinfo_test",
"host": true
},
diff --git a/include/cpu_features_cache_info.h b/include/cpu_features_cache_info.h
index b7cc046..1a61ee1 100644
--- a/include/cpu_features_cache_info.h
+++ b/include/cpu_features_cache_info.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index fae9f70..4b231a1 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -79,6 +79,10 @@
#define CPU_FEATURES_OS_WINDOWS
#endif
+#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
+#define CPU_FEATURES_OS_DARWIN
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Compilers
////////////////////////////////////////////////////////////////////////////////
diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h
index a42ecdf..d85d46d 100644
--- a/include/cpuinfo_aarch64.h
+++ b/include/cpuinfo_aarch64.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,62 +15,62 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
-#include "cpu_features_macros.h"
#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
- int fp : 1; // Floating-point.
- int asimd : 1; // Advanced SIMD.
- int evtstrm : 1; // Generic timer generated events.
- int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
- int pmull : 1; // Polynomial multiply long.
- int sha1 : 1; // Hardware-accelerated SHA1.
- int sha2 : 1; // Hardware-accelerated SHA2-256.
- int crc32 : 1; // Hardware-accelerated CRC-32.
- int atomics : 1; // Armv8.1 atomic instructions.
- int fphp : 1; // Half-precision floating point support.
- int asimdhp : 1; // Advanced SIMD half-precision support.
- int cpuid : 1; // Access to certain ID registers.
- int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
- int jscvt : 1; // Support for JavaScript conversion.
- int fcma : 1; // Floating point complex numbers.
- int lrcpc : 1; // Support for weaker release consistency.
- int dcpop : 1; // Data persistence writeback.
- int sha3 : 1; // Hardware-accelerated SHA3.
- int sm3 : 1; // Hardware-accelerated SM3.
- int sm4 : 1; // Hardware-accelerated SM4.
- int asimddp : 1; // Dot product instruction.
- int sha512 : 1; // Hardware-accelerated SHA512.
- int sve : 1; // Scalable Vector Extension.
- int asimdfhm : 1; // Additional half-precision instructions.
- int dit : 1; // Data independent timing.
- int uscat : 1; // Unaligned atomics support.
- int ilrcpc : 1; // Additional support for weaker release consistency.
- int flagm : 1; // Flag manipulation instructions.
- int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
- int sb : 1; // Speculation barrier.
- int paca : 1; // Address authentication.
- int pacg : 1; // Generic authentication.
- int dcpodp : 1; // Data cache clean to point of persistence.
- int sve2 : 1; // Scalable Vector Extension (version 2).
- int sveaes : 1; // SVE AES instructions.
- int svepmull : 1; // SVE polynomial multiply long instructions.
- int svebitperm : 1; // SVE bit permute instructions.
- int svesha3 : 1; // SVE SHA3 instructions.
- int svesm4 : 1; // SVE SM4 instructions.
- int flagm2 : 1; // Additional flag manipulation instructions.
- int frint : 1; // Floating point to integer rounding.
- int svei8mm : 1; // SVE Int8 matrix multiplication instructions.
- int svef32mm : 1; // SVE FP32 matrix multiplication instruction.
- int svef64mm : 1; // SVE FP64 matrix multiplication instructions.
- int svebf16 : 1; // SVE BFloat16 instructions.
- int i8mm : 1; // Int8 matrix multiplication instructions.
- int bf16 : 1; // BFloat16 instructions.
- int dgh : 1; // Data Gathering Hint instruction.
- int rng : 1; // True random number generator support.
- int bti : 1; // Branch target identification.
+ int fp : 1; // Floating-point.
+ int asimd : 1; // Advanced SIMD.
+ int evtstrm : 1; // Generic timer generated events.
+ int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
+ int pmull : 1; // Polynomial multiply long.
+ int sha1 : 1; // Hardware-accelerated SHA1.
+ int sha2 : 1; // Hardware-accelerated SHA2-256.
+ int crc32 : 1; // Hardware-accelerated CRC-32.
+ int atomics : 1; // Armv8.1 atomic instructions.
+ int fphp : 1; // Half-precision floating point support.
+ int asimdhp : 1; // Advanced SIMD half-precision support.
+ int cpuid : 1; // Access to certain ID registers.
+ int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
+ int jscvt : 1; // Support for JavaScript conversion.
+ int fcma : 1; // Floating point complex numbers.
+ int lrcpc : 1; // Support for weaker release consistency.
+ int dcpop : 1; // Data persistence writeback.
+ int sha3 : 1; // Hardware-accelerated SHA3.
+ int sm3 : 1; // Hardware-accelerated SM3.
+ int sm4 : 1; // Hardware-accelerated SM4.
+ int asimddp : 1; // Dot product instruction.
+ int sha512 : 1; // Hardware-accelerated SHA512.
+ int sve : 1; // Scalable Vector Extension.
+ int asimdfhm : 1; // Additional half-precision instructions.
+ int dit : 1; // Data independent timing.
+ int uscat : 1; // Unaligned atomics support.
+ int ilrcpc : 1; // Additional support for weaker release consistency.
+ int flagm : 1; // Flag manipulation instructions.
+ int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
+ int sb : 1; // Speculation barrier.
+ int paca : 1; // Address authentication.
+ int pacg : 1; // Generic authentication.
+ int dcpodp : 1; // Data cache clean to point of persistence.
+ int sve2 : 1; // Scalable Vector Extension (version 2).
+ int sveaes : 1; // SVE AES instructions.
+ int svepmull : 1; // SVE polynomial multiply long instructions.
+ int svebitperm : 1; // SVE bit permute instructions.
+ int svesha3 : 1; // SVE SHA3 instructions.
+ int svesm4 : 1; // SVE SM4 instructions.
+ int flagm2 : 1; // Additional flag manipulation instructions.
+ int frint : 1; // Floating point to integer rounding.
+ int svei8mm : 1; // SVE Int8 matrix multiplication instructions.
+ int svef32mm : 1; // SVE FP32 matrix multiplication instruction.
+ int svef64mm : 1; // SVE FP64 matrix multiplication instructions.
+ int svebf16 : 1; // SVE BFloat16 instructions.
+ int i8mm : 1; // Int8 matrix multiplication instructions.
+ int bf16 : 1; // BFloat16 instructions.
+ int dgh : 1; // Data Gathering Hint instruction.
+ int rng : 1; // True random number generator support.
+ int bti : 1; // Branch target identification.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
diff --git a/include/cpuinfo_arm.h b/include/cpuinfo_arm.h
index d15471f..0952d7c 100644
--- a/include/cpuinfo_arm.h
+++ b/include/cpuinfo_arm.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,8 +16,9 @@
#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
#include <stdint.h> // uint32_t
-#include "cpu_features_macros.h"
+
#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
@@ -25,30 +26,33 @@ typedef struct {
int swp : 1; // SWP instruction (atomic read-modify-write)
int half : 1; // Half-word loads and stores
int thumb : 1; // Thumb (16-bit instruction set)
- int _26bit : 1; // "26 Bit" Model (Processor status register folded into program counter)
+ int _26bit : 1; // "26 Bit" Model (Processor status register folded into
+ // program counter)
int fastmult : 1; // 32x32->64-bit multiplication
int fpa : 1; // Floating point accelerator
int vfp : 1; // Vector Floating Point.
- int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)
- int java : 1; // Jazelle (Java bytecode accelerator)
- int iwmmxt : 1; // Intel Wireless MMX Technology.
- int crunch : 1; // MaverickCrunch coprocessor
- int thumbee : 1; // ThumbEE
- int neon : 1; // Advanced SIMD.
- int vfpv3 : 1; // VFP version 3
+ int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all
+ // others above)
+ int java : 1; // Jazelle (Java bytecode accelerator)
+ int iwmmxt : 1; // Intel Wireless MMX Technology.
+ int crunch : 1; // MaverickCrunch coprocessor
+ int thumbee : 1; // ThumbEE
+ int neon : 1; // Advanced SIMD.
+ int vfpv3 : 1; // VFP version 3
int vfpv3d16 : 1; // VFP version 3 with 16 D-registers
int tls : 1; // TLS register
int vfpv4 : 1; // VFP version 4 with fast context switching
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
int vfpd32 : 1; // VFP with 32 D-registers
- int lpae : 1; // Large Physical Address Extension (>4GB physical memory on 32-bit architecture)
- int evtstrm : 1; // kernel event stream using generic architected timer
- int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
- int pmull : 1; // Polynomial multiply long.
- int sha1 : 1; // Hardware-accelerated SHA1.
- int sha2 : 1; // Hardware-accelerated SHA2-256.
- int crc32 : 1; // Hardware-accelerated CRC-32.
+ int lpae : 1; // Large Physical Address Extension (>4GB physical memory on
+ // 32-bit architecture)
+ int evtstrm : 1; // kernel event stream using generic architected timer
+ int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
+ int pmull : 1; // Polynomial multiply long.
+ int sha1 : 1; // Hardware-accelerated SHA1.
+ int sha2 : 1; // Hardware-accelerated SHA2-256.
+ int crc32 : 1; // Hardware-accelerated CRC-32.
// Make sure to update ArmFeaturesEnum below if you add a field here.
} ArmFeatures;
diff --git a/include/cpuinfo_mips.h b/include/cpuinfo_mips.h
index d82ae85..9e5e7fc 100644
--- a/include/cpuinfo_mips.h
+++ b/include/cpuinfo_mips.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
-#include "cpu_features_macros.h"
#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/cpuinfo_ppc.h b/include/cpuinfo_ppc.h
index eaac7da..f691194 100644
--- a/include/cpuinfo_ppc.h
+++ b/include/cpuinfo_ppc.h
@@ -15,8 +15,8 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
-#include "cpu_features_macros.h"
#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
#include "internal/hwcaps.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h
index c21a46a..8d40f71 100644
--- a/include/cpuinfo_x86.h
+++ b/include/cpuinfo_x86.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/include/internal/bit_utils.h b/include/internal/bit_utils.h
index bc965cb..3467ff9 100644
--- a/include/internal/bit_utils.h
+++ b/include/internal/bit_utils.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
+
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/cpuid_x86.h b/include/internal/cpuid_x86.h
index 754ca38..33327a4 100644
--- a/include/internal/cpuid_x86.h
+++ b/include/internal/cpuid_x86.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@ typedef struct {
uint32_t eax, ebx, ecx, edx;
} Leaf;
-Leaf CpuIdEx(uint32_t leaf_id, int ecx);
+// Returns the result of a call to the cpuid instruction.
+Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx);
// Returns the eax value of the XCR0 register.
uint32_t GetXCR0Eax(void);
diff --git a/include/internal/filesystem.h b/include/internal/filesystem.h
index 3378881..d8f2f6a 100644
--- a/include/internal/filesystem.h
+++ b/include/internal/filesystem.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <stddef.h>
#include <stdint.h>
+
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index f0e91b3..62037c8 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,7 +17,9 @@
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
+#include <stdbool.h>
#include <stdint.h>
+
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
@@ -169,6 +171,8 @@ typedef struct {
} HardwareCapabilities;
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+ const HardwareCapabilities hwcaps);
typedef struct {
char platform[64]; // 0 terminated string
diff --git a/include/internal/stack_line_reader.h b/include/internal/stack_line_reader.h
index c540f6b..39c1b8b 100644
--- a/include/internal/stack_line_reader.h
+++ b/include/internal/stack_line_reader.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/include/internal/string_view.h b/include/internal/string_view.h
index aa3779c..64fed40 100644
--- a/include/internal/string_view.h
+++ b/include/internal/string_view.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/unix_features_aggregator.h b/include/internal/unix_features_aggregator.h
deleted file mode 100644
index bed668d..0000000
--- a/include/internal/unix_features_aggregator.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2017 Google Inc.
-//
-// 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.
-
-// CapabilityConfig provides a way to map cpu features to hardware caps and
-// /proc/cpuinfo flags. We then provide functions to update capabilities from
-// either source.
-#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
-#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
-
-#include <ctype.h>
-#include <stdint.h>
-#include "cpu_features_macros.h"
-#include "internal/hwcaps.h"
-#include "internal/string_view.h"
-
-CPU_FEATURES_START_CPP_NAMESPACE
-
-// Use the following macro to declare setter functions to be used in
-// CapabilityConfig.
-#define DECLARE_SETTER(FeatureType, FeatureName) \
- static void set_##FeatureName(void* const features, bool value) { \
- ((FeatureType*)features)->FeatureName = value; \
- }
-
-// Use the following macro to declare getter functions to be used in
-// CapabilityConfig.
-#define DECLARE_GETTER(FeatureType, FeatureName) \
- static int get_##FeatureName(void* const features) { \
- return ((FeatureType*)features)->FeatureName; \
- }
-
-#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \
- DECLARE_SETTER(FeatureType, FeatureName) \
- DECLARE_GETTER(FeatureType, FeatureName)
-
-// Describes the relationship between hardware caps and /proc/cpuinfo flags.
-typedef struct {
- const HardwareCapabilities hwcaps_mask;
- const char* const proc_cpuinfo_flag;
- void (*set_bit)(void* const, bool); // setter for the corresponding bit.
- int (*get_bit)(void* const); // getter for the corresponding bit.
-} CapabilityConfig;
-
-// For every config, looks into flags_line for the presence of the
-// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly.
-// Note: features is a pointer to the underlying Feature struct.
-void CpuFeatures_SetFromFlags(const size_t configs_size,
- const CapabilityConfig* configs,
- const StringView flags_line,
- void* const features);
-
-// For every config, looks into hwcaps for the presence of the feature. Calls
-// `set_bit` with true if the hardware capability is found.
-// Note: features is a pointer to the underlying Feature struct.
-void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
- const CapabilityConfig* configs,
- const HardwareCapabilities hwcaps,
- void* const features);
-
-CPU_FEATURES_END_CPP_NAMESPACE
-#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
diff --git a/ndk_compat/cpu-features.c b/ndk_compat/cpu-features.c
index ca49ac3..27ff7bb 100644
--- a/ndk_compat/cpu-features.c
+++ b/ndk_compat/cpu-features.c
@@ -1,11 +1,12 @@
#include "cpu-features.h"
+
+#include <pthread.h>
+
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include <pthread.h>
-
#if defined(CPU_FEATURES_ARCH_ARM)
#include "cpuinfo_arm.h"
#elif defined(CPU_FEATURES_ARCH_X86)
diff --git a/ndk_compat/ndk-compat-test.c b/ndk_compat/ndk-compat-test.c
index 782dbbf..e4005d4 100644
--- a/ndk_compat/ndk-compat-test.c
+++ b/ndk_compat/ndk-compat-test.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+
#include "cpu-features.h"
int main() {
diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c
index 6cd5308..0a52718 100644
--- a/src/cpuinfo_aarch64.c
+++ b/src/cpuinfo_aarch64.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,120 +14,70 @@
#include "cpuinfo_aarch64.h"
+#include <assert.h>
+#include <ctype.h>
+
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-
-#include <assert.h>
-#include <ctype.h>
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, aes)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sve)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dit)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sb)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, paca)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpodp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sve2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sveaes)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svepmull)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svebitperm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svesha3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svesm4)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, frint)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svei8mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svef32mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svef64mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svebf16)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, i8mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, bf16)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dgh)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, rng)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, bti)
-
-static const CapabilityConfig kConfigs[] = {
- [AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp, &get_fp},
- [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd, &get_asimd},
- [AARCH64_EVTSTRM] = {{AARCH64_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm},
- [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes, &get_aes},
- [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull, &get_pmull},
- [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1, &get_sha1},
- [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2, &get_sha2},
- [AARCH64_CRC32] = {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32, &get_crc32},
- [AARCH64_ATOMICS] = {{AARCH64_HWCAP_ATOMICS, 0}, "atomics", &set_atomics, &get_atomics},
- [AARCH64_FPHP] = {{AARCH64_HWCAP_FPHP, 0}, "fphp", &set_fphp, &get_fphp},
- [AARCH64_ASIMDHP] = {{AARCH64_HWCAP_ASIMDHP, 0}, "asimdhp", &set_asimdhp, &get_asimdhp},
- [AARCH64_CPUID] = {{AARCH64_HWCAP_CPUID, 0}, "cpuid", &set_cpuid, &get_cpuid},
- [AARCH64_ASIMDRDM] = {{AARCH64_HWCAP_ASIMDRDM, 0}, "asimdrdm", &set_asimdrdm, &get_asimdrdm},
- [AARCH64_JSCVT] = {{AARCH64_HWCAP_JSCVT, 0}, "jscvt", &set_jscvt, &get_jscvt},
- [AARCH64_FCMA] = {{AARCH64_HWCAP_FCMA, 0}, "fcma", &set_fcma, &get_fcma},
- [AARCH64_LRCPC] = {{AARCH64_HWCAP_LRCPC, 0}, "lrcpc", &set_lrcpc, &get_lrcpc},
- [AARCH64_DCPOP] = {{AARCH64_HWCAP_DCPOP, 0}, "dcpop", &set_dcpop, &get_dcpop},
- [AARCH64_SHA3] = {{AARCH64_HWCAP_SHA3, 0}, "sha3", &set_sha3, &get_sha3},
- [AARCH64_SM3] = {{AARCH64_HWCAP_SM3, 0}, "sm3", &set_sm3, &get_sm3},
- [AARCH64_SM4] = {{AARCH64_HWCAP_SM4, 0}, "sm4", &set_sm4, &get_sm4},
- [AARCH64_ASIMDDP] = {{AARCH64_HWCAP_ASIMDDP, 0}, "asimddp", &set_asimddp, &get_asimddp},
- [AARCH64_SHA512] = {{AARCH64_HWCAP_SHA512, 0}, "sha512", &set_sha512, &get_sha512},
- [AARCH64_SVE] = {{AARCH64_HWCAP_SVE, 0}, "sve", &set_sve, &get_sve},
- [AARCH64_ASIMDFHM] = {{AARCH64_HWCAP_ASIMDFHM, 0}, "asimdfhm", &set_asimdfhm, &get_asimdfhm},
- [AARCH64_DIT] = {{AARCH64_HWCAP_DIT, 0}, "dit", &set_dit, &get_dit},
- [AARCH64_USCAT] = {{AARCH64_HWCAP_USCAT, 0}, "uscat", &set_uscat, &get_uscat},
- [AARCH64_ILRCPC] = {{AARCH64_HWCAP_ILRCPC, 0}, "ilrcpc", &set_ilrcpc, &get_ilrcpc},
- [AARCH64_FLAGM] = {{AARCH64_HWCAP_FLAGM, 0}, "flagm", &set_flagm, &get_flagm},
- [AARCH64_SSBS] = {{AARCH64_HWCAP_SSBS, 0}, "ssbs", &set_ssbs, &get_ssbs},
- [AARCH64_SB] = {{AARCH64_HWCAP_SB, 0}, "sb", &set_sb, &get_sb},
- [AARCH64_PACA] = {{AARCH64_HWCAP_PACA, 0}, "paca", &set_paca, &get_paca},
- [AARCH64_PACG] = {{AARCH64_HWCAP_PACG, 0}, "pacg", &set_pacg, &get_pacg},
- [AARCH64_DCPODP] = {{0, AARCH64_HWCAP2_DCPODP}, "dcpodp", &set_dcpodp, &get_dcpodp},
- [AARCH64_SVE2] = {{0, AARCH64_HWCAP2_SVE2}, "sve2", &set_sve2, &get_sve2},
- [AARCH64_SVEAES] = {{0, AARCH64_HWCAP2_SVEAES}, "sveaes", &set_sveaes, &get_sveaes},
- [AARCH64_SVEPMULL] = {{0, AARCH64_HWCAP2_SVEPMULL}, "svepmull", &set_svepmull, &get_svepmull},
- [AARCH64_SVEBITPERM] = {{0, AARCH64_HWCAP2_SVEBITPERM}, "svebitperm", &set_svebitperm, &get_svebitperm},
- [AARCH64_SVESHA3] = {{0, AARCH64_HWCAP2_SVESHA3}, "svesha3", &set_svesha3, &get_svesha3},
- [AARCH64_SVESM4] = {{0, AARCH64_HWCAP2_SVESM4}, "svesm4", &set_svesm4, &get_svesm4},
- [AARCH64_FLAGM2] = {{0, AARCH64_HWCAP2_FLAGM2}, "flagm2", &set_flagm2, &get_flagm2},
- [AARCH64_FRINT] = {{0, AARCH64_HWCAP2_FRINT}, "frint", &set_frint, &get_frint},
- [AARCH64_SVEI8MM] = {{0, AARCH64_HWCAP2_SVEI8MM}, "svei8mm", &set_svei8mm, &get_svei8mm},
- [AARCH64_SVEF32MM] = {{0, AARCH64_HWCAP2_SVEF32MM}, "svef32mm", &set_svef32mm, &get_svef32mm},
- [AARCH64_SVEF64MM] = {{0, AARCH64_HWCAP2_SVEF64MM}, "svef64mm", &set_svef64mm, &get_svef64mm},
- [AARCH64_SVEBF16] = {{0, AARCH64_HWCAP2_SVEBF16}, "svebf16", &set_svebf16, &get_svebf16},
- [AARCH64_I8MM] = {{0, AARCH64_HWCAP2_I8MM}, "i8mm", &set_i8mm, &get_i8mm},
- [AARCH64_BF16] = {{0, AARCH64_HWCAP2_BF16}, "bf16", &set_bf16, &get_bf16},
- [AARCH64_DGH] = {{0, AARCH64_HWCAP2_DGH}, "dgh", &set_dgh, &get_dgh},
- [AARCH64_RNG] = {{0, AARCH64_HWCAP2_RNG}, "rng", &set_rng, &get_rng},
- [AARCH64_BTI] = {{0, AARCH64_HWCAP2_BTI}, "bti", &set_bti, &get_bti},
-};
-
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURES \
+ FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
+ FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
+ FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
+ FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
+ FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
+ FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
+ FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
+ FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
+ FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
+ FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
+ FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
+ FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
+ FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
+ FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
+ FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
+ FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
+ FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
+ FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
+ FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
+ FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
+ FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
+ FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
+ FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
+ FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
+ FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
+ FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
+ FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
+ FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
+ FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
+ FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
+ FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
+ FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
+ FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
+ FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
+ FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
+ FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
+ FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
+ AARCH64_HWCAP2_SVEBITPERM) \
+ FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
+ FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
+ FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
+ FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
+ FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
+ FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
+ FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
+ FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
+ FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
+ FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
+ FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
+ FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
+ FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
+#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
+#include "define_tables.h"
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info) {
@@ -135,7 +85,10 @@ static bool HandleAarch64Line(const LineResult result,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
+ for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+ kSetters[i](&info->features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -166,17 +119,18 @@ static void FillProcCpuInfoData(Aarch64Info* const info) {
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void) {
- assert(kConfigsSize == AARCH64_LAST_);
-
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
Aarch64Info info = kEmptyAarch64Info;
FillProcCpuInfoData(&info);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -186,13 +140,11 @@ Aarch64Info GetAarch64Info(void) {
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value) {
- if(value >= kConfigsSize)
- return false;
- return kConfigs[value].get_bit((Aarch64Features*)features);
+ if (value >= AARCH64_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
- if(value >= kConfigsSize)
- return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= AARCH64_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c
index 741c99a..0f216bf 100644
--- a/src/cpuinfo_arm.c
+++ b/src/cpuinfo_arm.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,75 +14,47 @@
#include "cpuinfo_arm.h"
+#include <assert.h>
+#include <ctype.h>
+
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-#include <assert.h>
-#include <ctype.h>
-
-DECLARE_SETTER_AND_GETTER(ArmFeatures, swp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, half)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, java)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, neon)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, tls)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, aes)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32)
-
-static const CapabilityConfig kConfigs[] = {
- [ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp, &get_swp}, //
- [ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half, &get_half}, //
- [ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb, &get_thumb}, //
- [ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit, &get__26bit}, //
- [ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult, &get_fastmult}, //
- [ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa, &get_fpa}, //
- [ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp, &get_vfp}, //
- [ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp, &get_edsp}, //
- [ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java, &get_java}, //
- [ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt, &get_iwmmxt}, //
- [ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch, &get_crunch}, //
- [ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee, &get_thumbee}, //
- [ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon, &get_neon}, //
- [ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3, &get_vfpv3}, //
- [ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16, &get_vfpv3d16}, //
- [ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls, &get_tls}, //
- [ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4, &get_vfpv4}, //
- [ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva, &get_idiva}, //
- [ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt, &get_idivt}, //
- [ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32, &get_vfpd32}, //
- [ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae, &get_lpae}, //
- [ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, //
- [ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes, &get_aes}, //
- [ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull, &get_pmull}, //
- [ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1, &get_sha1}, //
- [ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2, &get_sha2}, //
- [ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32, &get_crc32}, //
-};
-
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURES \
+ FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \
+ FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \
+ FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \
+ FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \
+ FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
+ FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \
+ FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \
+ FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \
+ FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \
+ FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \
+ FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \
+ FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \
+ FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \
+ FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \
+ FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \
+ FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \
+ FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \
+ FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \
+ FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \
+ FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \
+ FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \
+ FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \
+ FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \
+ FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \
+ FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \
+ FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \
+ FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
+#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
+#include "define_tables.h"
typedef struct {
bool processor_reports_armv6;
@@ -104,7 +76,10 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
+ for (size_t i = 0; i < ARM_LAST_; ++i) {
+ kSetters[i](&info->features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -119,8 +94,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
const StringView digits =
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
- } else if (CpuFeatures_StringView_IsEquals(key, str("Processor"))
- || CpuFeatures_StringView_IsEquals(key, str("model name")) ) {
+ } else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) ||
+ CpuFeatures_StringView_IsEquals(key, str("model name"))) {
// Android reports this in a non-Linux standard "Processor" but sometimes
// also in "model name", Linux reports it only in "model name"
// see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases
@@ -210,9 +185,12 @@ ArmInfo GetArmInfo(void) {
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
FillProcCpuInfoData(&info, &proc_cpu_info_data);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < ARM_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
FixErrors(&info, &proc_cpu_info_data);
@@ -224,13 +202,11 @@ ArmInfo GetArmInfo(void) {
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value) {
- if(value >= kConfigsSize)
- return false;
- return kConfigs[value].get_bit((ArmFeatures*)features);
+ if (value >= ARM_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
- if(value >= kConfigsSize)
- return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= ARM_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c
index 0564bb8..83e959f 100644
--- a/src/cpuinfo_mips.c
+++ b/src/cpuinfo_mips.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,23 +14,21 @@
#include "cpuinfo_mips.h"
+#include <assert.h>
+
#include "internal/filesystem.h"
+#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-
-#include <assert.h>
-
-DECLARE_SETTER_AND_GETTER(MipsFeatures, msa)
-DECLARE_SETTER_AND_GETTER(MipsFeatures, eva)
-DECLARE_SETTER_AND_GETTER(MipsFeatures, r6)
-static const CapabilityConfig kConfigs[] = {
- [MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa, &get_msa}, //
- [MIPS_EVA] = {{0, 0}, "eva", &set_eva, &get_eva}, //
- [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6, &get_r6}, //
-};
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURES \
+ FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
+ FEATURE(MIPS_EVA, eva, "eva", 0, 0) \
+ FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
+#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
+#include "define_tables.h"
static bool HandleMipsLine(const LineResult result,
MipsFeatures* const features) {
@@ -38,7 +36,10 @@ static bool HandleMipsLine(const LineResult result,
// See tests for an example.
if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features);
+ for (size_t i = 0; i < MIPS_LAST_; ++i) {
+ kSetters[i](features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
}
}
return !result.eof;
@@ -61,17 +62,18 @@ static void FillProcCpuInfoData(MipsFeatures* const features) {
static const MipsInfo kEmptyMipsInfo;
MipsInfo GetMipsInfo(void) {
- assert(kConfigsSize == MIPS_LAST_);
-
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
MipsInfo info = kEmptyMipsInfo;
FillProcCpuInfoData(&info.features);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < MIPS_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -80,13 +82,11 @@ MipsInfo GetMipsInfo(void) {
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value) {
- if(value >= kConfigsSize)
- return false;
- return kConfigs[value].get_bit((MipsFeatures*)features);
+ if (value >= MIPS_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
- if(value >= kConfigsSize)
- return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= MIPS_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c
index c088f86..24401f9 100644
--- a/src/cpuinfo_ppc.c
+++ b/src/cpuinfo_ppc.c
@@ -12,105 +12,69 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "cpuinfo_ppc.h"
+
#include <assert.h>
#include <stdbool.h>
#include <string.h>
-#include "cpuinfo_ppc.h"
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc32)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc64)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc601)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, altivec)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, fpu)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, mmu)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, mac_4xx)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, unifiedcache)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, spe)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, efpsingle)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, efpdouble)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, no_tb)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power4)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power5)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power5plus)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, cell)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, booke)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, smt)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, icachesnoop)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch205)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, pa6t)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, dfp)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power6ext)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch206)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, vsx)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, pseries_perfmon_compat)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, truele)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppcle)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch207)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, dscr)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ebb)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, isel)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, tar)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, vcrypto)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_nosc)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch300)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ieee128)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, darn)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, scv)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_no_suspend)
-static const CapabilityConfig kConfigs[] = {
- [PPC_32] = {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32, &get_ppc32},
- [PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64, &get_ppc64},
- [PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601, &get_ppc601},
- [PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec, &get_altivec},
- [PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu, &get_fpu},
- [PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu, &get_mmu},
- [PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx, &get_mac_4xx},
- [PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache, &get_unifiedcache},
- [PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe, &get_spe},
- [PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle, &get_efpsingle},
- [PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble, &get_efpdouble},
- [PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb, &get_no_tb},
- [PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4, &get_power4},
- [PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5, &get_power5},
- [PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus, &get_power5plus},
- [PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell, &get_cell},
- [PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke, &get_booke},
- [PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt, &get_smt},
- [PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop, &get_icachesnoop},
- [PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205, &get_arch205},
- [PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t, &get_pa6t},
- [PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp, &get_dfp},
- [PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext, &get_power6ext},
- [PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206, &get_arch206},
- [PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx, &get_vsx},
- [PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0}, "archpmu",
- &set_pseries_perfmon_compat, &get_pseries_perfmon_compat},
- [PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele, &get_truele},
- [PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle, &get_ppcle},
- [PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207, &get_arch207},
- [PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm, &get_htm},
- [PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr, &get_dscr},
- [PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb, &get_ebb},
- [PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel, &get_isel},
- [PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar, &get_tar},
- [PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto, &get_vcrypto},
- [PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc, &get_htm_nosc},
- [PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300, &get_arch300},
- [PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128, &get_ieee128},
- [PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn, &get_darn},
- [PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv, &get_scv},
- [PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend,
- &get_htm_no_suspend},
-};
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURES \
+ FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \
+ FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \
+ FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \
+ FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \
+ FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \
+ FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \
+ FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \
+ FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", \
+ PPC_FEATURE_UNIFIED_CACHE, 0) \
+ FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \
+ FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", \
+ PPC_FEATURE_HAS_EFP_SINGLE, 0) \
+ FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", \
+ PPC_FEATURE_HAS_EFP_DOUBLE, 0) \
+ FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \
+ FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \
+ FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \
+ FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \
+ FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \
+ FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \
+ FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \
+ FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \
+ 0) \
+ FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \
+ FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \
+ FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \
+ FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \
+ FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \
+ FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \
+ FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \
+ PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \
+ FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \
+ FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \
+ FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \
+ FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \
+ FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \
+ FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \
+ FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \
+ FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \
+ FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \
+ FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \
+ FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \
+ FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \
+ FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \
+ FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
+ FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
+ PPC_FEATURE2_HTM_NO_SUSPEND)
+#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
+#include "define_tables.h"
static bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings) {
@@ -156,10 +120,12 @@ PPCInfo GetPPCInfo(void) {
* the auxilary vector.
*/
PPCInfo info = kEmptyPPCInfo;
-
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < PPC_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -178,13 +144,11 @@ PPCPlatformStrings GetPPCPlatformStrings(void) {
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value) {
- if(value >= kConfigsSize)
- return false;
- return kConfigs[value].get_bit((PPCFeatures*)features);
+ if (value >= PPC_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
- if(value >= kConfigsSize)
- return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= PPC_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c
index d5edd30..378ed05 100644
--- a/src/cpuinfo_x86.c
+++ b/src/cpuinfo_x86.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +25,91 @@
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
#endif
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags global tables.
+#define DEFINE_TABLE_FEATURES \
+ FEATURE(X86_FPU, fpu, "fpu", 0, 0) \
+ FEATURE(X86_TSC, tsc, "tsc", 0, 0) \
+ FEATURE(X86_CX8, cx8, "cx8", 0, 0) \
+ FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0) \
+ FEATURE(X86_MMX, mmx, "mmx", 0, 0) \
+ FEATURE(X86_AES, aes, "aes", 0, 0) \
+ FEATURE(X86_ERMS, erms, "erms", 0, 0) \
+ FEATURE(X86_F16C, f16c, "f16c", 0, 0) \
+ FEATURE(X86_FMA4, fma4, "fma4", 0, 0) \
+ FEATURE(X86_FMA3, fma3, "fma3", 0, 0) \
+ FEATURE(X86_VAES, vaes, "vaes", 0, 0) \
+ FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0) \
+ FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0) \
+ FEATURE(X86_HLE, hle, "hle", 0, 0) \
+ FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0) \
+ FEATURE(X86_RTM, rtm, "rtm", 0, 0) \
+ FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0) \
+ FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0) \
+ FEATURE(X86_CLWB, clwb, "clwb", 0, 0) \
+ FEATURE(X86_SSE, sse, "sse", 0, 0) \
+ FEATURE(X86_SSE2, sse2, "sse2", 0, 0) \
+ FEATURE(X86_SSE3, sse3, "sse3", 0, 0) \
+ FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0) \
+ FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0) \
+ FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0) \
+ FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0) \
+ FEATURE(X86_AVX, avx, "avx", 0, 0) \
+ FEATURE(X86_AVX2, avx2, "avx2", 0, 0) \
+ FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0) \
+ FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0) \
+ FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0) \
+ FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0) \
+ FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0) \
+ FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0) \
+ FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0) \
+ FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0) \
+ FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0) \
+ FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0) \
+ FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0) \
+ FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0) \
+ FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0) \
+ FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0) \
+ FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0) \
+ FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0) \
+ FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0) \
+ FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0) \
+ FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", \
+ 0, 0) \
+ FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0) \
+ FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0) \
+ FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0) \
+ FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0) \
+ FEATURE(X86_SMX, smx, "smx", 0, 0) \
+ FEATURE(X86_SGX, sgx, "sgx", 0, 0) \
+ FEATURE(X86_CX16, cx16, "cx16", 0, 0) \
+ FEATURE(X86_SHA, sha, "sha", 0, 0) \
+ FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0) \
+ FEATURE(X86_MOVBE, movbe, "movbe", 0, 0) \
+ FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0) \
+ FEATURE(X86_DCA, dca, "dca", 0, 0) \
+ FEATURE(X86_SS, ss, "ss", 0, 0)
+#define DEFINE_TABLE_FEATURE_TYPE X86Features
+#define DEFINE_TABLE_DONT_GENERATE_HWCAPS
+#include "define_tables.h"
+
+// The following includes are necessary to provide SSE detections on pre-AVX
+// microarchitectures.
+#if defined(CPU_FEATURES_OS_WINDOWS)
+#include <windows.h> // IsProcessorFeaturePresent
+#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+#include "internal/filesystem.h" // Needed to parse /proc/cpuinfo
+#include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo
+#include "internal/string_view.h" // Needed to parse /proc/cpuinfo
+#elif defined(CPU_FEATURES_OS_DARWIN)
+#if !defined(HAVE_SYSCTLBYNAME)
+#error "Darwin needs support for sysctlbyname"
+#endif
+#include <sys/sysctl.h>
+#else
+#error "Unsupported OS"
+#endif // CPU_FEATURES_OS
+
////////////////////////////////////////////////////////////////////////////////
// Definitions for CpuId and GetXCR0Eax.
////////////////////////////////////////////////////////////////////////////////
@@ -35,7 +120,7 @@
#include <cpuid.h>
-Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
+Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
Leaf leaf;
__cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
return leaf;
@@ -55,7 +140,7 @@ uint32_t GetXCR0Eax(void) {
#include <immintrin.h>
#include <intrin.h> // For __cpuidex()
-Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
+Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
Leaf leaf;
int data[4];
__cpuidex(data, leaf_id, ecx);
@@ -72,13 +157,13 @@ uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC."
#endif
-static Leaf CpuId(uint32_t leaf_id) { return CpuIdEx(leaf_id, 0); }
+static Leaf CpuId(uint32_t leaf_id) { return GetCpuidLeaf(leaf_id, 0); }
static const Leaf kEmptyLeaf;
static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) {
if (leaf_id <= max_cpuid_leaf) {
- return CpuIdEx(leaf_id, ecx);
+ return GetCpuidLeaf(leaf_id, ecx);
} else {
return kEmptyLeaf;
}
@@ -1082,27 +1167,115 @@ static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
// Internal structure to hold the OS support for vector operations.
// Avoid to recompute them since each call to cpuid is ~100 cycles.
typedef struct {
- bool have_sse;
+ bool have_sse_via_os;
+ bool have_sse_via_cpuid;
bool have_avx;
bool have_avx512;
bool have_amx;
} OsSupport;
+static const OsSupport kEmptyOsSupport;
+
+static OsSupport CheckOsSupport(const uint32_t max_cpuid_leaf) {
+ const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
+ const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
+ const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
+ const bool have_xcr0 = have_xsave && have_osxsave;
+
+ OsSupport os_support = kEmptyOsSupport;
+
+ if (have_xcr0) {
+ // AVX capable cpu will expose XCR0.
+ const uint32_t xcr0_eax = GetXCR0Eax();
+ os_support.have_sse_via_cpuid = HasXmmOsXSave(xcr0_eax);
+ os_support.have_avx = HasYmmOsXSave(xcr0_eax);
+ os_support.have_avx512 = HasZmmOsXSave(xcr0_eax);
+ os_support.have_amx = HasTmmOsXSave(xcr0_eax);
+ } else {
+ // Atom based or older cpus need to ask the OS for sse support.
+ os_support.have_sse_via_os = true;
+ }
+
+ return os_support;
+}
+
+#if defined(CPU_FEATURES_OS_WINDOWS)
+#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+extern bool GetWindowsIsProcessorFeaturePresent(DWORD);
+#else // CPU_FEATURES_MOCK_CPUID_X86
+static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+ return IsProcessorFeaturePresent(ProcessorFeature);
+}
+#endif
+#endif // CPU_FEATURES_OS_WINDOWS
+
+#if defined(CPU_FEATURES_OS_DARWIN)
+#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+extern bool GetDarwinSysCtlByName(const char*);
+#else // CPU_FEATURES_MOCK_CPUID_X86
+static bool GetDarwinSysCtlByName(const char* name) {
+ int enabled;
+ size_t enabled_len = sizeof(enabled);
+ const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0);
+ return failure ? false : enabled;
+}
+#endif
+#endif // CPU_FEATURES_OS_DARWIN
+
+static void DetectSseViaOs(X86Features* features) {
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
+ features->sse =
+ GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
+ features->sse2 =
+ GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+ features->sse3 =
+ GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
+#elif defined(CPU_FEATURES_OS_DARWIN)
+ // Handling Darwin platform through sysctlbyname.
+ features->sse = GetDarwinSysCtlByName("hw.optional.sse");
+ features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2");
+ features->sse3 = GetDarwinSysCtlByName("hw.optional.sse3");
+ features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3");
+ features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1");
+ features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2");
+#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+ // Handling Linux platform through /proc/cpuinfo.
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ const LineResult result = StackLineReader_NextLine(&reader);
+ const StringView line = result.line;
+ StringView key, value;
+ if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+ if (CpuFeatures_StringView_IsEquals(key, str("flags"))) {
+ features->sse = CpuFeatures_StringView_HasWord(value, "sse");
+ features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2");
+ features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3");
+ features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3");
+ features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1");
+ features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2");
+ break;
+ }
+ }
+ if (result.eof) break;
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+#else
+#error "Unsupported fallback detection of SSE OS support."
+#endif
+}
+
// Reference https://en.wikipedia.org/wiki/CPUID.
-static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
- OsSupport* os_support) {
+static void ParseCpuId(const uint32_t max_cpuid_leaf,
+ const OsSupport os_support, X86Info* info) {
const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1);
- const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
- const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
- const uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0;
- os_support->have_sse = HasXmmOsXSave(xcr0_eax);
- os_support->have_avx = HasYmmOsXSave(xcr0_eax);
- os_support->have_avx512 = HasZmmOsXSave(xcr0_eax);
- os_support->have_amx = HasTmmOsXSave(xcr0_eax);
-
const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4);
@@ -1142,7 +1315,9 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
features->vaes = IsBitSet(leaf_7.ecx, 9);
features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
- if (os_support->have_sse) {
+ if (os_support.have_sse_via_os) {
+ DetectSseViaOs(features);
+ } else if (os_support.have_sse_via_cpuid) {
features->sse = IsBitSet(leaf_1.edx, 25);
features->sse2 = IsBitSet(leaf_1.edx, 26);
features->sse3 = IsBitSet(leaf_1.ecx, 0);
@@ -1151,13 +1326,13 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
}
- if (os_support->have_avx) {
+ if (os_support.have_avx) {
features->fma3 = IsBitSet(leaf_1.ecx, 12);
features->avx = IsBitSet(leaf_1.ecx, 28);
features->avx2 = IsBitSet(leaf_7.ebx, 5);
}
- if (os_support->have_avx512) {
+ if (os_support.have_avx512) {
features->avx512f = IsBitSet(leaf_7.ebx, 16);
features->avx512cd = IsBitSet(leaf_7.ebx, 28);
features->avx512er = IsBitSet(leaf_7.ebx, 27);
@@ -1179,7 +1354,7 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8);
}
- if (os_support->have_amx) {
+ if (os_support.have_amx) {
features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
features->amx_tile = IsBitSet(leaf_7.edx, 24);
features->amx_int8 = IsBitSet(leaf_7.edx, 25);
@@ -1195,7 +1370,7 @@ static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) {
X86Features* const features = &info->features;
- if (os_support.have_sse) {
+ if (os_support.have_sse_via_cpuid) {
features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
}
@@ -1205,22 +1380,21 @@ static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) {
}
static const X86Info kEmptyX86Info;
-static const OsSupport kEmptyOsSupport;
static const CacheInfo kEmptyCacheInfo;
X86Info GetX86Info(void) {
X86Info info = kEmptyX86Info;
- OsSupport os_support = kEmptyOsSupport;
const Leaf leaf_0 = CpuId(0);
const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
SetVendor(leaf_0, info.vendor);
if (is_intel || is_amd) {
const uint32_t max_cpuid_leaf = leaf_0.eax;
- ParseCpuId(max_cpuid_leaf, &info, &os_support);
- }
- if (is_amd) {
- ParseExtraAMDCpuId(&info, os_support);
+ const OsSupport os_support = CheckOsSupport(max_cpuid_leaf);
+ ParseCpuId(max_cpuid_leaf, os_support, &info);
+ if (is_amd) {
+ ParseExtraAMDCpuId(&info, os_support);
+ }
}
return info;
}
@@ -1380,259 +1554,13 @@ void FillX86BrandString(char brand_string[49]) {
int GetX86FeaturesEnumValue(const X86Features* features,
X86FeaturesEnum value) {
- switch (value) {
- case X86_FPU:
- return features->fpu;
- case X86_TSC:
- return features->tsc;
- case X86_CX8:
- return features->cx8;
- case X86_CLFSH:
- return features->clfsh;
- case X86_MMX:
- return features->mmx;
- case X86_AES:
- return features->aes;
- case X86_ERMS:
- return features->erms;
- case X86_F16C:
- return features->f16c;
- case X86_FMA4:
- return features->fma4;
- case X86_FMA3:
- return features->fma3;
- case X86_VAES:
- return features->vaes;
- case X86_VPCLMULQDQ:
- return features->vpclmulqdq;
- case X86_BMI1:
- return features->bmi1;
- case X86_HLE:
- return features->hle;
- case X86_BMI2:
- return features->bmi2;
- case X86_RTM:
- return features->rtm;
- case X86_RDSEED:
- return features->rdseed;
- case X86_CLFLUSHOPT:
- return features->clflushopt;
- case X86_CLWB:
- return features->clwb;
- case X86_SSE:
- return features->sse;
- case X86_SSE2:
- return features->sse2;
- case X86_SSE3:
- return features->sse3;
- case X86_SSSE3:
- return features->ssse3;
- case X86_SSE4_1:
- return features->sse4_1;
- case X86_SSE4_2:
- return features->sse4_2;
- case X86_SSE4A:
- return features->sse4a;
- case X86_AVX:
- return features->avx;
- case X86_AVX2:
- return features->avx2;
- case X86_AVX512F:
- return features->avx512f;
- case X86_AVX512CD:
- return features->avx512cd;
- case X86_AVX512ER:
- return features->avx512er;
- case X86_AVX512PF:
- return features->avx512pf;
- case X86_AVX512BW:
- return features->avx512bw;
- case X86_AVX512DQ:
- return features->avx512dq;
- case X86_AVX512VL:
- return features->avx512vl;
- case X86_AVX512IFMA:
- return features->avx512ifma;
- case X86_AVX512VBMI:
- return features->avx512vbmi;
- case X86_AVX512VBMI2:
- return features->avx512vbmi2;
- case X86_AVX512VNNI:
- return features->avx512vnni;
- case X86_AVX512BITALG:
- return features->avx512bitalg;
- case X86_AVX512VPOPCNTDQ:
- return features->avx512vpopcntdq;
- case X86_AVX512_4VNNIW:
- return features->avx512_4vnniw;
- case X86_AVX512_4VBMI2:
- return features->avx512_4vbmi2;
- case X86_AVX512_SECOND_FMA:
- return features->avx512_second_fma;
- case X86_AVX512_4FMAPS:
- return features->avx512_4fmaps;
- case X86_AVX512_BF16:
- return features->avx512_bf16;
- case X86_AVX512_VP2INTERSECT:
- return features->avx512_vp2intersect;
- case X86_AMX_BF16:
- return features->amx_bf16;
- case X86_AMX_TILE:
- return features->amx_tile;
- case X86_AMX_INT8:
- return features->amx_int8;
- case X86_PCLMULQDQ:
- return features->pclmulqdq;
- case X86_SMX:
- return features->smx;
- case X86_SGX:
- return features->sgx;
- case X86_CX16:
- return features->cx16;
- case X86_SHA:
- return features->sha;
- case X86_POPCNT:
- return features->popcnt;
- case X86_MOVBE:
- return features->movbe;
- case X86_RDRND:
- return features->rdrnd;
- case X86_DCA:
- return features->dca;
- case X86_SS:
- return features->ss;
- case X86_LAST_:
- break;
- }
- return false;
+ if (value >= X86_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
- switch (value) {
- case X86_FPU:
- return "fpu";
- case X86_TSC:
- return "tsc";
- case X86_CX8:
- return "cx8";
- case X86_CLFSH:
- return "clfsh";
- case X86_MMX:
- return "mmx";
- case X86_AES:
- return "aes";
- case X86_ERMS:
- return "erms";
- case X86_F16C:
- return "f16c";
- case X86_FMA4:
- return "fma4";
- case X86_FMA3:
- return "fma3";
- case X86_VAES:
- return "vaes";
- case X86_VPCLMULQDQ:
- return "vpclmulqdq";
- case X86_BMI1:
- return "bmi1";
- case X86_HLE:
- return "hle";
- case X86_BMI2:
- return "bmi2";
- case X86_RTM:
- return "rtm";
- case X86_RDSEED:
- return "rdseed";
- case X86_CLFLUSHOPT:
- return "clflushopt";
- case X86_CLWB:
- return "clwb";
- case X86_SSE:
- return "sse";
- case X86_SSE2:
- return "sse2";
- case X86_SSE3:
- return "sse3";
- case X86_SSSE3:
- return "ssse3";
- case X86_SSE4_1:
- return "sse4_1";
- case X86_SSE4_2:
- return "sse4_2";
- case X86_SSE4A:
- return "sse4a";
- case X86_AVX:
- return "avx";
- case X86_AVX2:
- return "avx2";
- case X86_AVX512F:
- return "avx512f";
- case X86_AVX512CD:
- return "avx512cd";
- case X86_AVX512ER:
- return "avx512er";
- case X86_AVX512PF:
- return "avx512pf";
- case X86_AVX512BW:
- return "avx512bw";
- case X86_AVX512DQ:
- return "avx512dq";
- case X86_AVX512VL:
- return "avx512vl";
- case X86_AVX512IFMA:
- return "avx512ifma";
- case X86_AVX512VBMI:
- return "avx512vbmi";
- case X86_AVX512VBMI2:
- return "avx512vbmi2";
- case X86_AVX512VNNI:
- return "avx512vnni";
- case X86_AVX512BITALG:
- return "avx512bitalg";
- case X86_AVX512VPOPCNTDQ:
- return "avx512vpopcntdq";
- case X86_AVX512_4VNNIW:
- return "avx512_4vnniw";
- case X86_AVX512_4VBMI2:
- return "avx512_4vbmi2";
- case X86_AVX512_SECOND_FMA:
- return "avx512_second_fma";
- case X86_AVX512_4FMAPS:
- return "avx512_4fmaps";
- case X86_AVX512_BF16:
- return "avx512_bf16";
- case X86_AVX512_VP2INTERSECT:
- return "avx512_vp2intersect";
- case X86_AMX_BF16:
- return "amx_bf16";
- case X86_AMX_TILE:
- return "amx_tile";
- case X86_AMX_INT8:
- return "amx_int8";
- case X86_PCLMULQDQ:
- return "pclmulqdq";
- case X86_SMX:
- return "smx";
- case X86_SGX:
- return "sgx";
- case X86_CX16:
- return "cx16";
- case X86_SHA:
- return "sha";
- case X86_POPCNT:
- return "popcnt";
- case X86_MOVBE:
- return "movbe";
- case X86_RDRND:
- return "rdrnd";
- case X86_DCA:
- return "dca";
- case X86_SS:
- return "ss";
- case X86_LAST_:
- break;
- }
- return "unknown_feature";
+ if (value >= X86_LAST_) return "unknown_feature";
+ return kCpuInfoFlags[value];
}
const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
diff --git a/src/define_tables.h b/src/define_tables.h
new file mode 100644
index 0000000..dc1485c
--- /dev/null
+++ b/src/define_tables.h
@@ -0,0 +1,67 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The following preprocessor constants must be defined before including this
+// file:
+// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
+// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
+
+// This file is to be included once per `cpuinfo_XXX.c` in order to construct
+// feature getters and setters functions as well as several enum indexed tables
+// from the db file.
+// - `kGetters` a table of getters function pointers from feature enum to
+// retrieve a feature,
+// - `kSetters` a table of setters function pointers from feature enum to set a
+// feature,
+// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
+// flags,
+// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
+// their feature enum.
+
+#ifndef SRC_DEFINE_TABLES_H_
+#define SRC_DEFINE_TABLES_H_
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
+static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
+#undef FEATURE
+
+#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
+ [ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
+static const HardwareCapabilities kHardwareCapabilities[] = {
+ DEFINE_TABLE_FEATURES};
+#undef FEATURE
+#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
+ static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) { \
+ features->NAME = value; \
+ } \
+ static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) { \
+ return features->NAME; \
+ }
+DEFINE_TABLE_FEATURES
+#undef FEATURE
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
+static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
+ bool) = {DEFINE_TABLE_FEATURES};
+#undef FEATURE
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
+static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
+ DEFINE_TABLE_FEATURES};
+#undef FEATURE
+
+#endif // SRC_DEFINE_TABLES_H_
diff --git a/src/filesystem.c b/src/filesystem.c
index 2f7083b..46c9906 100644
--- a/src/filesystem.c
+++ b/src/filesystem.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/src/hwcaps.c b/src/hwcaps.c
index 815e5c1..dd17e3b 100644
--- a/src/hwcaps.c
+++ b/src/hwcaps.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,14 +12,33 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "internal/hwcaps.h"
+
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
-#include "internal/hwcaps.h"
#include "internal/string_view.h"
+static bool IsSet(const uint32_t mask, const uint32_t value) {
+ if (mask == 0) return false;
+ return (value & mask) == mask;
+}
+
+bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+ const HardwareCapabilities hwcaps) {
+ return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
+ IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
+}
+
+#ifdef CPU_FEATURES_TEST
+// In test mode, hwcaps_for_testing will define the following functions.
+HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+PlatformType CpuFeatures_GetPlatformType(void);
+#else
+
+// Debug facilities
#if defined(NDEBUG)
#define D(...)
#else
@@ -35,9 +54,12 @@
// Implementation of GetElfHwcapFromGetauxval
////////////////////////////////////////////////////////////////////////////////
-#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
-// Implementation will be provided by test/hwcaps_for_testing.cc.
-#elif defined(HAVE_STRONG_GETAUXVAL)
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+#define AT_PLATFORM 15
+#define AT_BASE_PLATFORM 24
+
+#if defined(HAVE_STRONG_GETAUXVAL)
#include <sys/auxv.h>
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
return getauxval(hwcap_type);
@@ -59,17 +81,13 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
// initialization layer.
#include <dlfcn.h>
-#define AT_HWCAP 16
-#define AT_HWCAP2 26
-#define AT_PLATFORM 15
-#define AT_BASE_PLATFORM 24
typedef unsigned long getauxval_func_t(unsigned long);
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
uint32_t ret = 0;
- void* libc_handle = NULL;
- getauxval_func_t* func = NULL;
+ void *libc_handle = NULL;
+ getauxval_func_t *func = NULL;
dlerror(); // Cleaning error state before calling dlopen.
libc_handle = dlopen("libc.so", RTLD_NOW);
@@ -77,7 +95,7 @@ static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
D("Could not dlopen() C library: %s\n", dlerror());
return 0;
}
- func = (getauxval_func_t*)dlsym(libc_handle, "getauxval");
+ func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
if (!func) {
D("Could not find getauxval() in C library\n");
} else {
@@ -109,7 +127,7 @@ static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
return 0;
}
for (;;) {
- const int ret = CpuFeatures_ReadFile(fd, (char*)&entry, sizeof entry);
+ const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
if (ret < 0) {
D("Error while reading %s\n", filepath);
break;
@@ -160,3 +178,5 @@ PlatformType CpuFeatures_GetPlatformType(void) {
sizeof(type.base_platform));
return type;
}
+
+#endif // CPU_FEATURES_TEST
diff --git a/src/stack_line_reader.c b/src/stack_line_reader.c
index b2c48ba..ffc778d 100644
--- a/src/stack_line_reader.c
+++ b/src/stack_line_reader.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,12 +13,13 @@
// limitations under the License.
#include "internal/stack_line_reader.h"
-#include "internal/filesystem.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
+#include "internal/filesystem.h"
+
void StackLineReader_Initialize(StackLineReader* reader, int fd) {
reader->view.ptr = reader->buffer;
reader->view.size = 0;
diff --git a/src/string_view.c b/src/string_view.c
index 856731c..dc3158f 100644
--- a/src/string_view.c
+++ b/src/string_view.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/src/unix_features_aggregator.c b/src/unix_features_aggregator.c
deleted file mode 100644
index 1b43a36..0000000
--- a/src/unix_features_aggregator.c
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal/unix_features_aggregator.h"
-#include "internal/string_view.h"
-
-void CpuFeatures_SetFromFlags(const size_t configs_size,
- const CapabilityConfig* configs,
- const StringView flags_line,
- void* const features) {
- size_t i = 0;
- for (; i < configs_size; ++i) {
- const CapabilityConfig config = configs[i];
- config.set_bit(features, CpuFeatures_StringView_HasWord(
- flags_line, config.proc_cpuinfo_flag));
- }
-}
-
-static bool IsSet(const uint32_t mask, const uint32_t value) {
- if (mask == 0) return false;
- return (value & mask) == mask;
-}
-
-static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
- const HardwareCapabilities hwcaps) {
- return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
- IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
-}
-
-void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
- const CapabilityConfig* configs,
- const HardwareCapabilities hwcaps,
- void* const features) {
- size_t i = 0;
- for (; i < configs_size; ++i) {
- const CapabilityConfig* config = &configs[i];
- if (IsHwCapsSet(config->hwcaps_mask, hwcaps)) {
- config->set_bit(features, true);
- }
- }
-}
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index 0783648..c80ffc5 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@
// the data accordingly.
// We use a bump allocator to allocate strings and nodes of the tree,
-// Memory is not intented to be reclaimed.
+// Memory is not intended to be reclaimed.
typedef struct {
char* ptr;
size_t size;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index eb67ac0..c10e617 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -12,7 +12,6 @@ add_library(filesystem_for_testing filesystem_for_testing.cc)
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
##------------------------------------------------------------------------------
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
-target_compile_definitions(hwcaps_for_testing PUBLIC CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(stack_line_reader ../src/stack_line_reader.c)
@@ -23,7 +22,7 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
##------------------------------------------------------------------------------
-add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c)
+add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
#
@@ -46,15 +45,13 @@ add_executable(stack_line_reader_test stack_line_reader_test.cc)
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
##------------------------------------------------------------------------------
-## unix_features_aggregator_test
-add_executable(unix_features_aggregator_test unix_features_aggregator_test.cc)
-target_link_libraries(unix_features_aggregator_test all_libraries)
-add_test(NAME unix_features_aggregator_test COMMAND unix_features_aggregator_test)
-##------------------------------------------------------------------------------
## cpuinfo_x86_test
if(PROCESSOR_IS_X86)
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
+ if(APPLE)
+ target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
+ endif()
target_link_libraries(cpuinfo_x86_test all_libraries)
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
endif()
diff --git a/test/bit_utils_test.cc b/test/bit_utils_test.cc
index 9c8c1bb..3874e13 100644
--- a/test/bit_utils_test.cc
+++ b/test/bit_utils_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc
index 1bd0648..5afaaa8 100644
--- a/test/cpuinfo_aarch64_test.cc
+++ b/test/cpuinfo_aarch64_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,10 +13,10 @@
// limitations under the License.
#include "cpuinfo_aarch64.h"
-#include "filesystem_for_testing.h"
-#include "hwcaps_for_testing.h"
+#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
@@ -62,7 +62,8 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) {
}
TEST(CpuinfoAarch64Test, FromHardwareCap2) {
- SetHardwareCapabilities(AARCH64_HWCAP_FP, AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
+ SetHardwareCapabilities(AARCH64_HWCAP_FP,
+ AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
diff --git a/test/cpuinfo_arm_test.cc b/test/cpuinfo_arm_test.cc
index fa92e11..e0b08a4 100644
--- a/test/cpuinfo_arm_test.cc
+++ b/test/cpuinfo_arm_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,10 +13,10 @@
// limitations under the License.
#include "cpuinfo_arm.h"
-#include "filesystem_for_testing.h"
-#include "hwcaps_for_testing.h"
+#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
diff --git a/test/cpuinfo_mips_test.cc b/test/cpuinfo_mips_test.cc
index fbec04d..d734058 100644
--- a/test/cpuinfo_mips_test.cc
+++ b/test/cpuinfo_mips_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,13 +13,13 @@
// limitations under the License.
#include "cpuinfo_mips.h"
+
#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "gtest/gtest.h"
-
namespace cpu_features {
namespace {
diff --git a/test/cpuinfo_ppc_test.cc b/test/cpuinfo_ppc_test.cc
index 5d5e798..8f0cb65 100644
--- a/test/cpuinfo_ppc_test.cc
+++ b/test/cpuinfo_ppc_test.cc
@@ -13,12 +13,12 @@
// limitations under the License.
#include "cpuinfo_ppc.h"
+
#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
-#include "gtest/gtest.h"
-
namespace cpu_features {
namespace {
diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc
index 3c80eee..636d0f9 100644
--- a/test/cpuinfo_x86_test.cc
+++ b/test/cpuinfo_x86_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,20 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "cpuinfo_x86.h"
+
#include <cassert>
#include <cstdio>
#include <map>
+#include <set>
+#if defined(CPU_FEATURES_OS_WINDOWS)
+#include <windows.h> // IsProcessorFeaturePresent
+#endif // CPU_FEATURES_OS_WINDOWS
+#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
-
-#include "cpuinfo_x86.h"
#include "internal/cpuid_x86.h"
namespace cpu_features {
class FakeCpu {
public:
- Leaf CpuIdEx(uint32_t leaf_id, int ecx) const {
+ Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const {
const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
if (itr != cpuid_leaves_.end()) {
return itr->second;
@@ -43,22 +48,66 @@ class FakeCpu {
xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
}
+#if defined(CPU_FEATURES_OS_DARWIN)
+ bool GetDarwinSysCtlByName(std::string name) const {
+ return darwin_sysctlbyname_.count(name);
+ }
+
+ void SetDarwinSysCtlByName(std::string name) {
+ darwin_sysctlbyname_.insert(name);
+ }
+#endif // CPU_FEATURES_OS_DARWIN
+
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+ return windows_isprocessorfeaturepresent_.count(ProcessorFeature);
+ }
+
+ void SetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+ windows_isprocessorfeaturepresent_.insert(ProcessorFeature);
+ }
+#endif // CPU_FEATURES_OS_WINDOWS
+
private:
std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
+#if defined(CPU_FEATURES_OS_DARWIN)
+ std::set<std::string> darwin_sysctlbyname_;
+#endif // CPU_FEATURES_OS_DARWIN
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ std::set<DWORD> windows_isprocessorfeaturepresent_;
+#endif // CPU_FEATURES_OS_WINDOWS
uint32_t xcr0_eax_;
};
-auto* g_fake_cpu = new FakeCpu();
+FakeCpu* g_fake_cpu = nullptr;
-extern "C" Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
- return g_fake_cpu->CpuIdEx(leaf_id, ecx);
+extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+ return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
}
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
+#if defined(CPU_FEATURES_OS_DARWIN)
+extern "C" bool GetDarwinSysCtlByName(const char* name) {
+ return g_fake_cpu->GetDarwinSysCtlByName(name);
+}
+#endif // CPU_FEATURES_OS_DARWIN
+
+#if defined(CPU_FEATURES_OS_WINDOWS)
+extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
+ return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature);
+}
+#endif // CPU_FEATURES_OS_WINDOWS
+
namespace {
-TEST(CpuidX86Test, SandyBridge) {
+class CpuidX86Test : public ::testing::Test {
+ protected:
+ void SetUp() override { g_fake_cpu = new FakeCpu(); }
+ void TearDown() override { delete g_fake_cpu; }
+};
+
+TEST_F(CpuidX86Test, SandyBridge) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
@@ -104,7 +153,7 @@ TEST(CpuidX86Test, SandyBridge) {
const int KiB = 1024;
const int MiB = 1024 * KiB;
-TEST(CpuidX86Test, SandyBridgeTestOsSupport) {
+TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
@@ -118,7 +167,7 @@ TEST(CpuidX86Test, SandyBridgeTestOsSupport) {
EXPECT_TRUE(GetX86Info().features.avx);
}
-TEST(CpuidX86Test, SkyLake) {
+TEST_F(CpuidX86Test, SkyLake) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
@@ -133,7 +182,7 @@ TEST(CpuidX86Test, SkyLake) {
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
}
-TEST(CpuidX86Test, Branding) {
+TEST_F(CpuidX86Test, Branding) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -149,7 +198,7 @@ TEST(CpuidX86Test, Branding) {
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
}
-TEST(CpuidX86Test, KabyLakeCache) {
+TEST_F(CpuidX86Test, KabyLakeCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -198,7 +247,7 @@ TEST(CpuidX86Test, KabyLakeCache) {
EXPECT_EQ(info.levels[3].partitioning, 1);
}
-TEST(CpuidX86Test, HSWCache) {
+TEST_F(CpuidX86Test, HSWCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -246,8 +295,9 @@ TEST(CpuidX86Test, HSWCache) {
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
EXPECT_EQ(info.levels[3].partitioning, 1);
}
+
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
-TEST(CpuidX86Test, AMD_K15) {
+TEST_F(CpuidX86Test, AMD_K15) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
{{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
@@ -273,6 +323,208 @@ TEST(CpuidX86Test, AMD_K15) {
EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
}
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt
+TEST_F(CpuidX86Test, Nehalem) {
+ // Pre AVX cpus don't have xsave
+ g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_XMMI_INSTRUCTIONS_AVAILABLE);
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_SSE3_INSTRUCTIONS_AVAILABLE);
+#endif // CPU_FEATURES_OS_WINDOWS
+#if defined(CPU_FEATURES_OS_DARWIN)
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
+#endif // CPU_FEATURES_OS_DARWIN
+#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(processor :
+flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
+)");
+#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
+ g_fake_cpu->SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
+ {{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
+ {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
+ {{0x00000004, 0}, Leaf{0x1C004122, 0x00C0003F, 0x0000007F, 0x00000000}},
+ {{0x00000004, 0}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
+ {{0x00000004, 0}, Leaf{0x1C03C163, 0x03C0003F, 0x00000FFF, 0x00000002}},
+ {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00021120}},
+ {{0x00000006, 0}, Leaf{0x00000001, 0x00000002, 0x00000001, 0x00000000}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x0000000A, 0}, Leaf{0x07300403, 0x00000000, 0x00000000, 0x00000603}},
+ {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
+ {{0x0000000B, 0}, Leaf{0x00000004, 0x00000002, 0x00000201, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x28100000}},
+ {{0x80000002, 0}, Leaf{0x756E6547, 0x20656E69, 0x65746E49, 0x2952286C}},
+ {{0x80000003, 0}, Leaf{0x55504320, 0x20202020, 0x20202020, 0x40202020}},
+ {{0x80000004, 0}, Leaf{0x30303020, 0x20402030, 0x37382E31, 0x007A4847}},
+ {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x01006040, 0x00000000}},
+ {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
+ {{0x80000008, 0}, Leaf{0x00003028, 0x00000000, 0x00000000, 0x00000000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x1A);
+ EXPECT_EQ(info.stepping, 0x02);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM);
+
+ char brand_string[49];
+ FillX86BrandString(brand_string);
+ EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU @ 0000 @ 1.87GHz");
+
+ EXPECT_TRUE(info.features.sse);
+ EXPECT_TRUE(info.features.sse2);
+ EXPECT_TRUE(info.features.sse3);
+#ifndef CPU_FEATURES_OS_WINDOWS
+ // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+ // feature detection > sse3.
+ EXPECT_TRUE(info.features.ssse3);
+ EXPECT_TRUE(info.features.sse4_1);
+ EXPECT_TRUE(info.features.sse4_2);
+#endif // CPU_FEATURES_OS_WINDOWS
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
+TEST_F(CpuidX86Test, Atom) {
+ // Pre AVX cpus don't have xsave
+ g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_XMMI_INSTRUCTIONS_AVAILABLE);
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_XMMI64_INSTRUCTIONS_AVAILABLE);
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_SSE3_INSTRUCTIONS_AVAILABLE);
+#endif // CPU_FEATURES_OS_WINDOWS
+#if defined(CPU_FEATURES_OS_DARWIN)
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
+#endif // CPU_FEATURES_OS_DARWIN
+#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
+)");
+#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
+ g_fake_cpu->SetLeaves({
+ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
+ {{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
+ {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x00000004, 0}, Leaf{0x1C000121, 0x0140003F, 0x0000003F, 0x00000001}},
+ {{0x00000004, 1}, Leaf{0x1C000122, 0x01C0003F, 0x0000003F, 0x00000001}},
+ {{0x00000004, 2}, Leaf{0x1C00C143, 0x03C0003F, 0x000003FF, 0x00000001}},
+ {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x33000020}},
+ {{0x00000006, 0}, Leaf{0x00000005, 0x00000002, 0x00000009, 0x00000000}},
+ {{0x00000007, 0}, Leaf{0x00000000, 0x00002282, 0x00000000, 0x00000000}},
+ {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x0000000A, 0}, Leaf{0x07280203, 0x00000000, 0x00000000, 0x00004503}},
+ {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
+ {{0x0000000B, 1}, Leaf{0x00000004, 0x00000004, 0x00000201, 0x00000000}},
+ {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000101, 0x28100000}},
+ {{0x80000002, 0}, Leaf{0x20202020, 0x6E492020, 0x286C6574, 0x43202952}},
+ {{0x80000003, 0}, Leaf{0x72656C65, 0x52286E6F, 0x50432029, 0x4A202055}},
+ {{0x80000004, 0}, Leaf{0x30303931, 0x20402020, 0x39392E31, 0x007A4847}},
+ {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
+ {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x04008040, 0x00000000}},
+ {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
+ {{0x80000008, 0}, Leaf{0x00003024, 0x00000000, 0x00000000, 0x00000000}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x37);
+ EXPECT_EQ(info.stepping, 0x03);
+ EXPECT_EQ(GetX86Microarchitecture(&info),
+ X86Microarchitecture::INTEL_ATOM_SMT);
+
+ char brand_string[49];
+ FillX86BrandString(brand_string);
+ EXPECT_STREQ(brand_string, " Intel(R) Celeron(R) CPU J1900 @ 1.99GHz");
+
+ EXPECT_TRUE(info.features.sse);
+ EXPECT_TRUE(info.features.sse2);
+ EXPECT_TRUE(info.features.sse3);
+#ifndef CPU_FEATURES_OS_WINDOWS
+ // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+ // feature detection > sse3.
+ EXPECT_TRUE(info.features.ssse3);
+ EXPECT_TRUE(info.features.sse4_1);
+ EXPECT_TRUE(info.features.sse4_2);
+#endif // CPU_FEATURES_OS_WINDOWS
+}
+
+// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
+TEST_F(CpuidX86Test, P3) {
+ // Pre AVX cpus don't have xsave
+ g_fake_cpu->SetOsBackupsExtendedRegisters(false);
+#if defined(CPU_FEATURES_OS_WINDOWS)
+ g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
+ PF_XMMI_INSTRUCTIONS_AVAILABLE);
+#endif // CPU_FEATURES_OS_WINDOWS
+#if defined(CPU_FEATURES_OS_DARWIN)
+ g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
+#endif // CPU_FEATURES_OS_DARWIN
+#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+flags : fpu mmx sse
+)");
+#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
+ g_fake_cpu->SetLeaves({
+ {{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
+ {{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
+ {{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
+ {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x4CECC782, 0x00006778}},
+ });
+ const auto info = GetX86Info();
+
+ EXPECT_STREQ(info.vendor, "GenuineIntel");
+ EXPECT_EQ(info.family, 0x06);
+ EXPECT_EQ(info.model, 0x07);
+ EXPECT_EQ(info.stepping, 0x03);
+ EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN);
+
+ char brand_string[49];
+ FillX86BrandString(brand_string);
+ EXPECT_STREQ(brand_string, "");
+
+ EXPECT_TRUE(info.features.mmx);
+ EXPECT_TRUE(info.features.sse);
+ EXPECT_FALSE(info.features.sse2);
+ EXPECT_FALSE(info.features.sse3);
+#ifndef CPU_FEATURES_OS_WINDOWS
+ // Currently disabled on Windows as IsProcessorFeaturePresent do not support
+ // feature detection > sse3.
+ EXPECT_FALSE(info.features.ssse3);
+ EXPECT_FALSE(info.features.sse4_1);
+ EXPECT_FALSE(info.features.sse4_2);
+#endif // CPU_FEATURES_OS_WINDOWS
+}
+
// TODO(user): test what happens when xsave/osxsave are not present.
// TODO(user): test what happens when xmm/ymm/zmm os support are not
// present.
diff --git a/test/filesystem_for_testing.cc b/test/filesystem_for_testing.cc
index 0a11416..648a53e 100644
--- a/test/filesystem_for_testing.cc
+++ b/test/filesystem_for_testing.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/filesystem_for_testing.h b/test/filesystem_for_testing.h
index 7474b5f..ef717fd 100644
--- a/test/filesystem_for_testing.h
+++ b/test/filesystem_for_testing.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/hwcaps_for_testing.cc b/test/hwcaps_for_testing.cc
index 07f68e8..a8086a0 100644
--- a/test/hwcaps_for_testing.cc
+++ b/test/hwcaps_for_testing.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "hwcaps_for_testing.h"
+
#include <string.h>
-#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
namespace cpu_features {
diff --git a/test/hwcaps_for_testing.h b/test/hwcaps_for_testing.h
index 0d03777..bcab82e 100644
--- a/test/hwcaps_for_testing.h
+++ b/test/hwcaps_for_testing.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/stack_line_reader_test.cc b/test/stack_line_reader_test.cc
index c8f9691..9ac5388 100644
--- a/test/stack_line_reader_test.cc
+++ b/test/stack_line_reader_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,8 +13,8 @@
// limitations under the License.
#include "internal/stack_line_reader.h"
-#include "filesystem_for_testing.h"
+#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
namespace cpu_features {
diff --git a/test/string_view_test.cc b/test/string_view_test.cc
index 0b6c7c2..ca3e023 100644
--- a/test/string_view_test.cc
+++ b/test/string_view_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -117,13 +117,13 @@ TEST(StringViewTest, CpuFeatures_StringView_Back) {
TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) {
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")),
- str("first middle last"));
+ str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")),
- str("first middle last"));
+ str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")),
- str("first middle last"));
+ str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
- str("first middle last"));
+ str("first middle last"));
}
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) {
diff --git a/test/unix_features_aggregator_test.cc b/test/unix_features_aggregator_test.cc
deleted file mode 100644
index 9017644..0000000
--- a/test/unix_features_aggregator_test.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2017 Google Inc.
-//
-// 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 <array>
-
-#include "internal/unix_features_aggregator.h"
-
-#include "gtest/gtest.h"
-
-namespace cpu_features {
-
-namespace {
-
-struct Features {
- bool a = false;
- bool b = false;
- bool c = false;
-};
-
-enum eFeatures {
- TEST_a,
- TEST_b,
- TEST_c
-};
-
-DECLARE_SETTER_AND_GETTER(Features, a)
-DECLARE_SETTER_AND_GETTER(Features, b)
-DECLARE_SETTER_AND_GETTER(Features, c)
-
-class LinuxFeatureAggregatorTest : public testing::Test {
- public:
- const std::array<CapabilityConfig, 3> kConfigs = {{
- {{0b0001, 0b0000}, "a", &set_a, &get_a},
- {{0b0010, 0b0000}, "b", &set_b, &get_b},
- {{0b0000, 0b1100}, "c", &set_c, &get_c}
- }};
-};
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str(""),
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-
- EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"),
- &features);
- EXPECT_TRUE(features.a);
- EXPECT_TRUE(features.b);
- EXPECT_TRUE(features.c);
-
- EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"),
- &features);
- EXPECT_TRUE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-
- EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
- EXPECT_FALSE(kConfigs[TEST_b].get_bit(&features));
- EXPECT_FALSE(kConfigs[TEST_c].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone) {
- HardwareCapabilities capability;
- capability.hwcaps = 0; // matches none
- capability.hwcaps2 = 0; // matches none
- Features features;
- CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet) {
- HardwareCapabilities capability;
- capability.hwcaps = 0b0010; // matches b but not a
- capability.hwcaps2 = 0b1111; // matches c
- Features features;
- CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_TRUE(features.b);
- EXPECT_TRUE(features.c);
-}
-
-} // namespace
-} // namespace cpu_features