aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Levillain <rpl@google.com>2020-09-23 11:30:09 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-09-23 11:30:09 +0000
commitb84b326210ae280310f9b4d18ecf2af74fffd8fe (patch)
tree1f0c0e0a541ebc3000a4c287f02e42a8cd8398b8
parent7ac203587452cdf6443806ed3497a83b72d3815a (diff)
parent35b546593a6f47a1403640895717d788a4ef2007 (diff)
downloadcpu_features-b84b326210ae280310f9b4d18ecf2af74fffd8fe.tar.gz
Merge v0.5.0 into master. am: 61cf9ace9e am: 49a0c3fa53 am: 65d05edc19 am: fdf4bb536f am: 35b546593a
Original change: https://android-review.googlesource.com/c/platform/external/cpu_features/+/1433444 Change-Id: I5f2835a5057c6568619639d3ef5111dbf3bd2ab3
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml12
-rw-r--r--Android.bp15
-rw-r--r--CMakeLists.txt22
-rw-r--r--LICENSE30
-rw-r--r--METADATA10
-rw-r--r--README.md29
-rw-r--r--include/cpu_features_macros.h101
-rw-r--r--include/cpuinfo_aarch64.h100
-rw-r--r--include/cpuinfo_x86.h23
-rw-r--r--include/internal/hwcaps.h44
-rw-r--r--include/internal/unix_features_aggregator.h12
-rw-r--r--ndk_compat/CMakeLists.txt1
-rw-r--r--ndk_compat/cpu-features.c2
-rw-r--r--src/cpuinfo_aarch64.c136
-rw-r--r--src/cpuinfo_arm.c170
-rw-r--r--src/cpuinfo_mips.c26
-rw-r--r--src/cpuinfo_ppc.c259
-rw-r--r--src/cpuinfo_x86.c1182
-rw-r--r--src/utils/list_cpu_features.c504
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/cpuinfo_aarch64_test.cc96
-rw-r--r--test/cpuinfo_arm_test.cc6
-rw-r--r--test/cpuinfo_x86_test.cc2
-rw-r--r--test/string_view_test.cc48
-rw-r--r--test/unix_features_aggregator_test.cc29
26 files changed, 2077 insertions, 789 deletions
diff --git a/.gitignore b/.gitignore
index 0690aa4..6285424 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
cmake_build/
+build/
+
+*.swp
diff --git a/.travis.yml b/.travis.yml
index e0b4f44..b5845be 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,8 +8,7 @@ cache:
- $HOME/cpu_features_archives
addons:
- apt:
- packages:
+ apt_packages:
- ninja-build
env:
@@ -41,14 +40,19 @@ matrix:
env:
TARGET=x86_64-windows
CMAKE_GENERATOR="Visual Studio 15 2017 Win64"
- - os: linux-ppc64le
+
+ # see: https://docs.travis-ci.com/user/multi-cpu-architectures/
+ - os: linux
+ arch: ppc64le
compiler: gcc
env:
TARGET=ppc64le-linux-gnu
- - os: linux-ppc64le
+ - os: linux
+ arch: ppc64le
compiler: clang
env:
TARGET=ppc64le-linux-gnu
+
# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
- os: linux
env:
diff --git a/Android.bp b/Android.bp
index c7569de..7632103 100644
--- a/Android.bp
+++ b/Android.bp
@@ -115,6 +115,21 @@ cc_binary {
static_libs: [
"libcpu_features",
],
+ arch: {
+ // Function `AddCacheInfo` in `src/utils/list_cpu_features.c` is only used on x86/x86_64 and
+ // triggers an error with `-Werror and `-Wunused-function` on other architectures; disable
+ // the latter flag to avoid compilation errors on those architectures.
+ arm: {
+ cflags: [
+ "-Wno-unused-function",
+ ],
+ },
+ arm64: {
+ cflags: [
+ "-Wno-unused-function",
+ ],
+ },
+ },
}
// Tests.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a0a57b..85102c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,12 @@
cmake_minimum_required(VERSION 3.0)
-project(CpuFeatures VERSION 0.1.0)
+# option() honors normal variables.
+# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
+if(POLICY CMP0077)
+ cmake_policy(SET CMP0077 NEW)
+endif()
+
+project(CpuFeatures VERSION 0.5.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
@@ -23,6 +29,12 @@ option(BUILD_SHARED_LIBS "Build library as shared." OFF)
# PIC
option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC
+# Force PIC on unix when building shared libs
+# see: https://en.wikipedia.org/wiki/Position-independent_code
+if(BUILD_SHARED_LIBS AND UNIX)
+ set(BUILD_PIC ON)
+endif()
+
include(CheckIncludeFile)
include(CheckSymbolExists)
include(GNUInstallDirs)
@@ -92,6 +104,7 @@ add_library(utils OBJECT
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
${PROJECT_SOURCE_DIR}/src/string_view.c
)
+set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
setup_include_and_definitions(utils)
#
@@ -135,6 +148,7 @@ set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}
target_include_directories(cpu_features
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
)
+add_library(CpuFeature::cpu_features ALIAS cpu_features)
#
# program : list_cpu_features
@@ -160,6 +174,12 @@ include(CTest)
if(BUILD_TESTING)
# Automatically incorporate googletest into the CMake Project if target not
# found.
+ enable_language(CXX)
+
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
+
if(NOT TARGET gtest OR NOT TARGET gmock_main)
# Download and unpack googletest at configure time.
configure_file(
diff --git a/LICENSE b/LICENSE
index 7a4a3ea..a7043c6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -199,4 +199,32 @@
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. \ No newline at end of file
+ limitations under the License.
+
+--------------------------------------------------------------------------------
+For files in the `ndk_compat` folder:
+--------------------------------------------------------------------------------
+
+Copyright (C) 2010 The Android Open Source Project
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/METADATA b/METADATA
index e2080b1..728702c 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
name: "cpu_features"
-description: "A cross platform C99 library to get CPU features at runtime."
+description: "A cross platform C99 library to get cpu features at runtime."
third_party {
url {
type: HOMEPAGE
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/cpu_features.git"
}
- version: "v0.4.1"
+ version: "v0.5.0"
license_type: NOTICE
last_upgrade_date {
- year: 2019
- month: 7
- day: 16
+ year: 2020
+ month: 9
+ day: 22
}
}
diff --git a/README.md b/README.md
index 29d7946..cbd115a 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,10 @@ instructions) at runtime.
- **Unit tested.**
<a name="codesample"></a>
+## Code samples
+
+**Note:** For C++ code, the library functions are defined in the `CpuFeatures` namespace.
+
### Checking features at runtime
Here's a simple example that executes a codepath if the CPU supports both the
@@ -38,6 +42,7 @@ AES and the SSE4.2 instruction sets:
```c
#include "cpuinfo_x86.h"
+// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
void Compute(void) {
@@ -59,6 +64,7 @@ features and then check whether AES and NEON are supported.
#include <stdbool.h>
#include "cpuinfo_arm.h"
+// For C++, add `using namespace CpuFeatures;`
static const ArmFeatures features = GetArmInfo().features;
static const bool has_aes_and_neon = features.aes && features.neon;
@@ -78,6 +84,7 @@ instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
#include <stdbool.h>
#include "cpuinfo_x86.h"
+// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
@@ -100,6 +107,7 @@ set&mdash;but only if it's not Sandy Bridge.
#include <stdbool.h>
#include "cpuinfo_x86.h"
+// For C++, add `using namespace CpuFeatures;`
static const X86Info info = GetX86Info();
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
@@ -112,7 +120,8 @@ This feature is currently available only for x86 microarchitectures.
<a name="usagesample"></a>
### Running sample code
-Building `cpu_features` brings a small executable to test the library.
+Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
+.
```shell
% ./build/list_cpu_features
@@ -172,3 +181,21 @@ See [LICENSE](LICENSE) for more information.
## Build with CMake
Please check the [CMake build instructions](cmake/README.md).
+
+<a name="quickstart"></a>
+### Quickstart with `Ninja`
+
+ - build `list_cpu_features`
+```
+ cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release
+ ninja -C/tmp/cpu_features
+ /tmp/cpu_features/list_cpu_features --json
+```
+
+ - run tests
+```
+ cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON
+ ninja -C/tmp/cpu_features
+ ninja -C/tmp/cpu_features test
+
+```
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index 2227160..fae9f70 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -118,26 +118,95 @@
// Use the following to check if a feature is known to be available at
// compile time. See README.md for an example.
#if defined(CPU_FEATURES_ARCH_X86)
-#define CPU_FEATURES_COMPILED_X86_AES defined(__AES__)
-#define CPU_FEATURES_COMPILED_X86_F16C defined(__F16C__)
-#define CPU_FEATURES_COMPILED_X86_BMI defined(__BMI__)
-#define CPU_FEATURES_COMPILED_X86_BMI2 defined(__BMI2__)
-#define CPU_FEATURES_COMPILED_X86_SSE (defined(__SSE__) || (_M_IX86_FP >= 1))
-#define CPU_FEATURES_COMPILED_X86_SSE2 (defined(__SSE2__) || (_M_IX86_FP >= 2))
-#define CPU_FEATURES_COMPILED_X86_SSE3 defined(__SSE3__)
-#define CPU_FEATURES_COMPILED_X86_SSSE3 defined(__SSSE3__)
-#define CPU_FEATURES_COMPILED_X86_SSE4_1 defined(__SSE4_1__)
-#define CPU_FEATURES_COMPILED_X86_SSE4_2 defined(__SSE4_2__)
-#define CPU_FEATURES_COMPILED_X86_AVX defined(__AVX__)
-#define CPU_FEATURES_COMPILED_x86_AVX2 defined(__AVX2__)
+
+#if defined(__AES__)
+#define CPU_FEATURES_COMPILED_X86_AES 1
+#else
+#define CPU_FEATURES_COMPILED_X86_AES 0
+#endif // defined(__AES__)
+
+#if defined(__F16C__)
+#define CPU_FEATURES_COMPILED_X86_F16C 1
+#else
+#define CPU_FEATURES_COMPILED_X86_F16C 0
+#endif // defined(__F16C__)
+
+#if defined(__BMI__)
+#define CPU_FEATURES_COMPILED_X86_BMI 1
+#else
+#define CPU_FEATURES_COMPILED_X86_BMI 0
+#endif // defined(__BMI__)
+
+#if defined(__BMI2__)
+#define CPU_FEATURES_COMPILED_X86_BMI2 1
+#else
+#define CPU_FEATURES_COMPILED_X86_BMI2 0
+#endif // defined(__BMI2__)
+
+#if (defined(__SSE__) || (_M_IX86_FP >= 1))
+#define CPU_FEATURES_COMPILED_X86_SSE 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSE 0
#endif
-#if defined(CPU_FEATURES_ARCH_ANY_ARM)
-#define CPU_FEATURES_COMPILED_ANY_ARM_NEON defined(__ARM_NEON__)
+#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
+#define CPU_FEATURES_COMPILED_X86_SSE2 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSE2 0
#endif
+#if defined(__SSE3__)
+#define CPU_FEATURES_COMPILED_X86_SSE3 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSE3 0
+#endif // defined(__SSE3__)
+
+#if defined(__SSSE3__)
+#define CPU_FEATURES_COMPILED_X86_SSSE3 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSSE3 0
+#endif // defined(__SSSE3__)
+
+#if defined(__SSE4_1__)
+#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
+#endif // defined(__SSE4_1__)
+
+#if defined(__SSE4_2__)
+#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
+#else
+#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
+#endif // defined(__SSE4_2__)
+
+#if defined(__AVX__)
+#define CPU_FEATURES_COMPILED_X86_AVX 1
+#else
+#define CPU_FEATURES_COMPILED_X86_AVX 0
+#endif // defined(__AVX__)
+
+#if defined(__AVX2__)
+#define CPU_FEATURES_COMPILED_X86_AVX2 1
+#else
+#define CPU_FEATURES_COMPILED_X86_AVX2 0
+#endif // defined(__AVX2__)
+
+#endif // defined(CPU_FEATURES_ARCH_X86)
+
+#if defined(CPU_FEATURES_ARCH_ANY_ARM)
+#if defined(__ARM_NEON__)
+#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
+#else
+#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
+#endif // defined(__ARM_NEON__)
+#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
+
#if defined(CPU_FEATURES_ARCH_MIPS)
-#define CPU_FEATURES_COMPILED_MIPS_MSA defined(__mips_msa)
-#endif
+#if defined(__mips_msa)
+#define CPU_FEATURES_COMPILED_MIPS_MSA 1
+#else
+#define CPU_FEATURES_COMPILED_MIPS_MSA 0
+#endif // defined(__mips_msa)
+#endif // defined(CPU_FEATURES_ARCH_MIPS)
#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h
index cd3a676..a42ecdf 100644
--- a/include/cpuinfo_aarch64.h
+++ b/include/cpuinfo_aarch64.h
@@ -21,13 +21,56 @@
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
- int fp : 1; // Floating-point.
- int asimd : 1; // Advanced SIMD.
- 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 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;
@@ -48,11 +91,54 @@ Aarch64Info GetAarch64Info(void);
typedef enum {
AARCH64_FP,
AARCH64_ASIMD,
+ AARCH64_EVTSTRM,
AARCH64_AES,
AARCH64_PMULL,
AARCH64_SHA1,
AARCH64_SHA2,
AARCH64_CRC32,
+ AARCH64_ATOMICS,
+ AARCH64_FPHP,
+ AARCH64_ASIMDHP,
+ AARCH64_CPUID,
+ AARCH64_ASIMDRDM,
+ AARCH64_JSCVT,
+ AARCH64_FCMA,
+ AARCH64_LRCPC,
+ AARCH64_DCPOP,
+ AARCH64_SHA3,
+ AARCH64_SM3,
+ AARCH64_SM4,
+ AARCH64_ASIMDDP,
+ AARCH64_SHA512,
+ AARCH64_SVE,
+ AARCH64_ASIMDFHM,
+ AARCH64_DIT,
+ AARCH64_USCAT,
+ AARCH64_ILRCPC,
+ AARCH64_FLAGM,
+ AARCH64_SSBS,
+ AARCH64_SB,
+ AARCH64_PACA,
+ AARCH64_PACG,
+ AARCH64_DCPODP,
+ AARCH64_SVE2,
+ AARCH64_SVEAES,
+ AARCH64_SVEPMULL,
+ AARCH64_SVEBITPERM,
+ AARCH64_SVESHA3,
+ AARCH64_SVESM4,
+ AARCH64_FLAGM2,
+ AARCH64_FRINT,
+ AARCH64_SVEI8MM,
+ AARCH64_SVEF32MM,
+ AARCH64_SVEF64MM,
+ AARCH64_SVEBF16,
+ AARCH64_I8MM,
+ AARCH64_BF16,
+ AARCH64_DGH,
+ AARCH64_RNG,
+ AARCH64_BTI,
AARCH64_LAST_,
} Aarch64FeaturesEnum;
diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h
index 4d51b60..c21a46a 100644
--- a/include/cpuinfo_x86.h
+++ b/include/cpuinfo_x86.h
@@ -1,4 +1,5 @@
// Copyright 2017 Google Inc.
+// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -31,6 +32,7 @@ typedef struct {
int aes : 1;
int erms : 1;
int f16c : 1;
+ int fma4 : 1;
int fma3 : 1;
int vaes : 1;
int vpclmulqdq : 1;
@@ -48,6 +50,7 @@ typedef struct {
int ssse3 : 1;
int sse4_1 : 1;
int sse4_2 : 1;
+ int sse4a : 1;
int avx : 1;
int avx2 : 1;
@@ -67,6 +70,13 @@ typedef struct {
int avx512vpopcntdq : 1;
int avx512_4vnniw : 1;
int avx512_4vbmi2 : 1;
+ int avx512_second_fma : 1;
+ int avx512_4fmaps : 1;
+ int avx512_bf16 : 1;
+ int avx512_vp2intersect : 1;
+ int amx_bf16 : 1;
+ int amx_tile : 1;
+ int amx_int8 : 1;
int pclmulqdq : 1;
int smx : 1;
@@ -116,7 +126,11 @@ typedef enum {
INTEL_ATOM_GMT, // GOLDMONT
INTEL_KBL, // KABY LAKE
INTEL_CFL, // COFFEE LAKE
+ INTEL_WHL, // WHISKEY LAKE
INTEL_CNL, // CANNON LAKE
+ INTEL_ICL, // ICE LAKE
+ INTEL_TGL, // TIGER LAKE
+ INTEL_SPR, // SAPPHIRE RAPIDS
AMD_HAMMER, // K8
AMD_K10, // K10
AMD_BOBCAT, // K14
@@ -147,6 +161,7 @@ typedef enum {
X86_AES,
X86_ERMS,
X86_F16C,
+ X86_FMA4,
X86_FMA3,
X86_VAES,
X86_VPCLMULQDQ,
@@ -163,6 +178,7 @@ typedef enum {
X86_SSSE3,
X86_SSE4_1,
X86_SSE4_2,
+ X86_SSE4A,
X86_AVX,
X86_AVX2,
X86_AVX512F,
@@ -180,6 +196,13 @@ typedef enum {
X86_AVX512VPOPCNTDQ,
X86_AVX512_4VNNIW,
X86_AVX512_4VBMI2,
+ X86_AVX512_SECOND_FMA,
+ X86_AVX512_4FMAPS,
+ X86_AVX512_BF16,
+ X86_AVX512_VP2INTERSECT,
+ X86_AMX_BF16,
+ X86_AMX_TILE,
+ X86_AMX_INT8,
X86_PCLMULQDQ,
X86_SMX,
X86_SGX,
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index 06a0f60..f0e91b3 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -28,11 +28,55 @@ CPU_FEATURES_START_CPP_NAMESPACE
// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
#define AARCH64_HWCAP_FP (1UL << 0)
#define AARCH64_HWCAP_ASIMD (1UL << 1)
+#define AARCH64_HWCAP_EVTSTRM (1UL << 2)
#define AARCH64_HWCAP_AES (1UL << 3)
#define AARCH64_HWCAP_PMULL (1UL << 4)
#define AARCH64_HWCAP_SHA1 (1UL << 5)
#define AARCH64_HWCAP_SHA2 (1UL << 6)
#define AARCH64_HWCAP_CRC32 (1UL << 7)
+#define AARCH64_HWCAP_ATOMICS (1UL << 8)
+#define AARCH64_HWCAP_FPHP (1UL << 9)
+#define AARCH64_HWCAP_ASIMDHP (1UL << 10)
+#define AARCH64_HWCAP_CPUID (1UL << 11)
+#define AARCH64_HWCAP_ASIMDRDM (1UL << 12)
+#define AARCH64_HWCAP_JSCVT (1UL << 13)
+#define AARCH64_HWCAP_FCMA (1UL << 14)
+#define AARCH64_HWCAP_LRCPC (1UL << 15)
+#define AARCH64_HWCAP_DCPOP (1UL << 16)
+#define AARCH64_HWCAP_SHA3 (1UL << 17)
+#define AARCH64_HWCAP_SM3 (1UL << 18)
+#define AARCH64_HWCAP_SM4 (1UL << 19)
+#define AARCH64_HWCAP_ASIMDDP (1UL << 20)
+#define AARCH64_HWCAP_SHA512 (1UL << 21)
+#define AARCH64_HWCAP_SVE (1UL << 22)
+#define AARCH64_HWCAP_ASIMDFHM (1UL << 23)
+#define AARCH64_HWCAP_DIT (1UL << 24)
+#define AARCH64_HWCAP_USCAT (1UL << 25)
+#define AARCH64_HWCAP_ILRCPC (1UL << 26)
+#define AARCH64_HWCAP_FLAGM (1UL << 27)
+#define AARCH64_HWCAP_SSBS (1UL << 28)
+#define AARCH64_HWCAP_SB (1UL << 29)
+#define AARCH64_HWCAP_PACA (1UL << 30)
+#define AARCH64_HWCAP_PACG (1UL << 31)
+
+#define AARCH64_HWCAP2_DCPODP (1UL << 0)
+#define AARCH64_HWCAP2_SVE2 (1UL << 1)
+#define AARCH64_HWCAP2_SVEAES (1UL << 2)
+#define AARCH64_HWCAP2_SVEPMULL (1UL << 3)
+#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4)
+#define AARCH64_HWCAP2_SVESHA3 (1UL << 5)
+#define AARCH64_HWCAP2_SVESM4 (1UL << 6)
+#define AARCH64_HWCAP2_FLAGM2 (1UL << 7)
+#define AARCH64_HWCAP2_FRINT (1UL << 8)
+#define AARCH64_HWCAP2_SVEI8MM (1UL << 9)
+#define AARCH64_HWCAP2_SVEF32MM (1UL << 10)
+#define AARCH64_HWCAP2_SVEF64MM (1UL << 11)
+#define AARCH64_HWCAP2_SVEBF16 (1UL << 12)
+#define AARCH64_HWCAP2_I8MM (1UL << 13)
+#define AARCH64_HWCAP2_BF16 (1UL << 14)
+#define AARCH64_HWCAP2_DGH (1UL << 15)
+#define AARCH64_HWCAP2_RNG (1UL << 16)
+#define AARCH64_HWCAP2_BTI (1UL << 17)
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#define ARM_HWCAP_SWP (1UL << 0)
diff --git a/include/internal/unix_features_aggregator.h b/include/internal/unix_features_aggregator.h
index 77661d4..bed668d 100644
--- a/include/internal/unix_features_aggregator.h
+++ b/include/internal/unix_features_aggregator.h
@@ -33,11 +33,23 @@ CPU_FEATURES_START_CPP_NAMESPACE
((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
diff --git a/ndk_compat/CMakeLists.txt b/ndk_compat/CMakeLists.txt
index d95e523..186708a 100644
--- a/ndk_compat/CMakeLists.txt
+++ b/ndk_compat/CMakeLists.txt
@@ -15,6 +15,7 @@ set (NDK_COMPAT_SRCS
add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS)
add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS})
setup_include_and_definitions(ndk_compat)
+target_include_directories(ndk_compat PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
diff --git a/ndk_compat/cpu-features.c b/ndk_compat/cpu-features.c
index 715dc4f..ca49ac3 100644
--- a/ndk_compat/cpu-features.c
+++ b/ndk_compat/cpu-features.c
@@ -115,7 +115,7 @@ static void android_cpuInit(void) {
if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
if (info.architecture >= 6)
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
- if (info.features.vfpv) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+ if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
if (info.features.vfpv4) {
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA;
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c
index 26a07d3..6cd5308 100644
--- a/src/cpuinfo_aarch64.c
+++ b/src/cpuinfo_aarch64.c
@@ -23,22 +23,108 @@
#include <assert.h>
#include <ctype.h>
-DECLARE_SETTER(Aarch64Features, fp)
-DECLARE_SETTER(Aarch64Features, asimd)
-DECLARE_SETTER(Aarch64Features, aes)
-DECLARE_SETTER(Aarch64Features, pmull)
-DECLARE_SETTER(Aarch64Features, sha1)
-DECLARE_SETTER(Aarch64Features, sha2)
-DECLARE_SETTER(Aarch64Features, crc32)
+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}, //
- [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd}, //
- [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes}, //
- [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull}, //
- [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1}, //
- [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2}, //
- [AARCH64_CRC32] {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32}, //
+ [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);
@@ -100,25 +186,9 @@ Aarch64Info GetAarch64Info(void) {
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value) {
- switch (value) {
- case AARCH64_FP:
- return features->fp;
- case AARCH64_ASIMD:
- return features->asimd;
- case AARCH64_AES:
- return features->aes;
- case AARCH64_PMULL:
- return features->pmull;
- case AARCH64_SHA1:
- return features->sha1;
- case AARCH64_SHA2:
- return features->sha2;
- case AARCH64_CRC32:
- return features->crc32;
- case AARCH64_LAST_:
- break;
- }
- return false;
+ if(value >= kConfigsSize)
+ return false;
+ return kConfigs[value].get_bit((Aarch64Features*)features);
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c
index 66c6d91..741c99a 100644
--- a/src/cpuinfo_arm.c
+++ b/src/cpuinfo_arm.c
@@ -24,62 +24,62 @@
#include <assert.h>
#include <ctype.h>
-DECLARE_SETTER(ArmFeatures, swp)
-DECLARE_SETTER(ArmFeatures, half)
-DECLARE_SETTER(ArmFeatures, thumb)
-DECLARE_SETTER(ArmFeatures, _26bit)
-DECLARE_SETTER(ArmFeatures, fastmult)
-DECLARE_SETTER(ArmFeatures, fpa)
-DECLARE_SETTER(ArmFeatures, vfp)
-DECLARE_SETTER(ArmFeatures, edsp)
-DECLARE_SETTER(ArmFeatures, java)
-DECLARE_SETTER(ArmFeatures, iwmmxt)
-DECLARE_SETTER(ArmFeatures, crunch)
-DECLARE_SETTER(ArmFeatures, thumbee)
-DECLARE_SETTER(ArmFeatures, neon)
-DECLARE_SETTER(ArmFeatures, vfpv3)
-DECLARE_SETTER(ArmFeatures, vfpv3d16)
-DECLARE_SETTER(ArmFeatures, tls)
-DECLARE_SETTER(ArmFeatures, vfpv4)
-DECLARE_SETTER(ArmFeatures, idiva)
-DECLARE_SETTER(ArmFeatures, idivt)
-DECLARE_SETTER(ArmFeatures, vfpd32)
-DECLARE_SETTER(ArmFeatures, lpae)
-DECLARE_SETTER(ArmFeatures, evtstrm)
-DECLARE_SETTER(ArmFeatures, aes)
-DECLARE_SETTER(ArmFeatures, pmull)
-DECLARE_SETTER(ArmFeatures, sha1)
-DECLARE_SETTER(ArmFeatures, sha2)
-DECLARE_SETTER(ArmFeatures, crc32)
+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}, //
- [ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half}, //
- [ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb}, //
- [ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit}, //
- [ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult}, //
- [ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa}, //
- [ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp}, //
- [ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp}, //
- [ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java}, //
- [ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt}, //
- [ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch}, //
- [ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee}, //
- [ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon}, //
- [ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3}, //
- [ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16}, //
- [ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls}, //
- [ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4}, //
- [ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva}, //
- [ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt}, //
- [ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32}, //
- [ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae}, //
- [ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm}, //
- [ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes}, //
- [ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull}, //
- [ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1}, //
- [ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2}, //
- [ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32}, //
+ [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);
@@ -224,65 +224,9 @@ ArmInfo GetArmInfo(void) {
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value) {
- switch (value) {
- case ARM_SWP:
- return features->swp;
- case ARM_HALF:
- return features->half;
- case ARM_THUMB:
- return features->thumb;
- case ARM_26BIT:
- return features->_26bit;
- case ARM_FASTMULT:
- return features->fastmult;
- case ARM_FPA:
- return features->fpa;
- case ARM_VFP:
- return features->vfp;
- case ARM_EDSP:
- return features->edsp;
- case ARM_JAVA:
- return features->java;
- case ARM_IWMMXT:
- return features->iwmmxt;
- case ARM_CRUNCH:
- return features->crunch;
- case ARM_THUMBEE:
- return features->thumbee;
- case ARM_NEON:
- return features->neon;
- case ARM_VFPV3:
- return features->vfpv3;
- case ARM_VFPV3D16:
- return features->vfpv3d16;
- case ARM_TLS:
- return features->tls;
- case ARM_VFPV4:
- return features->vfpv4;
- case ARM_IDIVA:
- return features->idiva;
- case ARM_IDIVT:
- return features->idivt;
- case ARM_VFPD32:
- return features->vfpd32;
- case ARM_LPAE:
- return features->lpae;
- case ARM_EVTSTRM:
- return features->evtstrm;
- case ARM_AES:
- return features->aes;
- case ARM_PMULL:
- return features->pmull;
- case ARM_SHA1:
- return features->sha1;
- case ARM_SHA2:
- return features->sha2;
- case ARM_CRC32:
- return features->crc32;
- case ARM_LAST_:
- break;
- }
- return false;
+ if(value >= kConfigsSize)
+ return false;
+ return kConfigs[value].get_bit((ArmFeatures*)features);
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c
index 8769211..0564bb8 100644
--- a/src/cpuinfo_mips.c
+++ b/src/cpuinfo_mips.c
@@ -21,14 +21,14 @@
#include <assert.h>
-DECLARE_SETTER(MipsFeatures, msa)
-DECLARE_SETTER(MipsFeatures, eva)
-DECLARE_SETTER(MipsFeatures, r6)
+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}, //
- [MIPS_EVA] = {{0, 0}, "eva", &set_eva}, //
- [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6}, //
+ [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);
@@ -80,17 +80,9 @@ MipsInfo GetMipsInfo(void) {
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value) {
- switch (value) {
- case MIPS_MSA:
- return features->msa;
- case MIPS_EVA:
- return features->eva;
- case MIPS_R6:
- return features->r6;
- case MIPS_LAST_:
- break;
- }
- return false;
+ if(value >= kConfigsSize)
+ return false;
+ return kConfigs[value].get_bit((MipsFeatures*)features);
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c
index d6c49f8..c088f86 100644
--- a/src/cpuinfo_ppc.c
+++ b/src/cpuinfo_ppc.c
@@ -23,92 +23,92 @@
#include "internal/string_view.h"
#include "internal/unix_features_aggregator.h"
-DECLARE_SETTER(PPCFeatures, ppc32)
-DECLARE_SETTER(PPCFeatures, ppc64)
-DECLARE_SETTER(PPCFeatures, ppc601)
-DECLARE_SETTER(PPCFeatures, altivec)
-DECLARE_SETTER(PPCFeatures, fpu)
-DECLARE_SETTER(PPCFeatures, mmu)
-DECLARE_SETTER(PPCFeatures, mac_4xx)
-DECLARE_SETTER(PPCFeatures, unifiedcache)
-DECLARE_SETTER(PPCFeatures, spe)
-DECLARE_SETTER(PPCFeatures, efpsingle)
-DECLARE_SETTER(PPCFeatures, efpdouble)
-DECLARE_SETTER(PPCFeatures, no_tb)
-DECLARE_SETTER(PPCFeatures, power4)
-DECLARE_SETTER(PPCFeatures, power5)
-DECLARE_SETTER(PPCFeatures, power5plus)
-DECLARE_SETTER(PPCFeatures, cell)
-DECLARE_SETTER(PPCFeatures, booke)
-DECLARE_SETTER(PPCFeatures, smt)
-DECLARE_SETTER(PPCFeatures, icachesnoop)
-DECLARE_SETTER(PPCFeatures, arch205)
-DECLARE_SETTER(PPCFeatures, pa6t)
-DECLARE_SETTER(PPCFeatures, dfp)
-DECLARE_SETTER(PPCFeatures, power6ext)
-DECLARE_SETTER(PPCFeatures, arch206)
-DECLARE_SETTER(PPCFeatures, vsx)
-DECLARE_SETTER(PPCFeatures, pseries_perfmon_compat)
-DECLARE_SETTER(PPCFeatures, truele)
-DECLARE_SETTER(PPCFeatures, ppcle)
-DECLARE_SETTER(PPCFeatures, arch207)
-DECLARE_SETTER(PPCFeatures, htm)
-DECLARE_SETTER(PPCFeatures, dscr)
-DECLARE_SETTER(PPCFeatures, ebb)
-DECLARE_SETTER(PPCFeatures, isel)
-DECLARE_SETTER(PPCFeatures, tar)
-DECLARE_SETTER(PPCFeatures, vcrypto)
-DECLARE_SETTER(PPCFeatures, htm_nosc)
-DECLARE_SETTER(PPCFeatures, arch300)
-DECLARE_SETTER(PPCFeatures, ieee128)
-DECLARE_SETTER(PPCFeatures, darn)
-DECLARE_SETTER(PPCFeatures, scv)
-DECLARE_SETTER(PPCFeatures, htm_no_suspend)
+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},
- [PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64},
- [PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601},
- [PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec},
- [PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu},
- [PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu},
- [PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx},
- [PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache},
- [PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe},
- [PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle},
- [PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble},
- [PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb},
- [PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4},
- [PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5},
- [PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus},
- [PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell},
- [PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke},
- [PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt},
- [PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop},
- [PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205},
- [PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t},
- [PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp},
- [PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext},
- [PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206},
- [PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx},
- [PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0},
- "archpmu",
- &set_pseries_perfmon_compat},
- [PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele},
- [PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle},
- [PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207},
- [PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm},
- [PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr},
- [PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb},
- [PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel},
- [PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar},
- [PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto},
- [PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc},
- [PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300},
- [PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128},
- [PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn},
- [PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv},
- [PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend},
+ [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);
@@ -178,96 +178,11 @@ PPCPlatformStrings GetPPCPlatformStrings(void) {
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value) {
- switch (value) {
- case PPC_32:
- return features->ppc32;
- case PPC_64:
- return features->ppc64;
- case PPC_601_INSTR:
- return features->ppc601;
- case PPC_HAS_ALTIVEC:
- return features->altivec;
- case PPC_HAS_FPU:
- return features->fpu;
- case PPC_HAS_MMU:
- return features->mmu;
- case PPC_HAS_4xxMAC:
- return features->mac_4xx;
- case PPC_UNIFIED_CACHE:
- return features->unifiedcache;
- case PPC_HAS_SPE:
- return features->spe;
- case PPC_HAS_EFP_SINGLE:
- return features->efpsingle;
- case PPC_HAS_EFP_DOUBLE:
- return features->efpdouble;
- case PPC_NO_TB:
- return features->no_tb;
- case PPC_POWER4:
- return features->power4;
- case PPC_POWER5:
- return features->power5;
- case PPC_POWER5_PLUS:
- return features->power5plus;
- case PPC_CELL:
- return features->cell;
- case PPC_BOOKE:
- return features->booke;
- case PPC_SMT:
- return features->smt;
- case PPC_ICACHE_SNOOP:
- return features->icachesnoop;
- case PPC_ARCH_2_05:
- return features->arch205;
- case PPC_PA6T:
- return features->pa6t;
- case PPC_HAS_DFP:
- return features->dfp;
- case PPC_POWER6_EXT:
- return features->power6ext;
- case PPC_ARCH_2_06:
- return features->arch206;
- case PPC_HAS_VSX:
- return features->vsx;
- case PPC_PSERIES_PERFMON_COMPAT:
- return features->pseries_perfmon_compat;
- case PPC_TRUE_LE:
- return features->truele;
- case PPC_PPC_LE:
- return features->ppcle;
- case PPC_ARCH_2_07:
- return features->arch207;
- case PPC_HTM:
- return features->htm;
- case PPC_DSCR:
- return features->dscr;
- case PPC_EBB:
- return features->ebb;
- case PPC_ISEL:
- return features->isel;
- case PPC_TAR:
- return features->tar;
- case PPC_VEC_CRYPTO:
- return features->vcrypto;
- case PPC_HTM_NOSC:
- return features->htm_nosc;
- case PPC_ARCH_3_00:
- return features->arch300;
- case PPC_HAS_IEEE128:
- return features->ieee128;
- case PPC_DARN:
- return features->darn;
- case PPC_SCV:
- return features->scv;
- case PPC_HTM_NO_SUSPEND:
- return features->htm_no_suspend;
- case PPC_LAST_:
- break;
- }
- return false;
+ if(value >= kConfigsSize)
+ return false;
+ return kConfigs[value].get_bit((PPCFeatures*)features);
}
-/* Have used the same names as glibc */
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
if(value >= kConfigsSize)
return "unknown feature";
diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c
index c997b7b..d5edd30 100644
--- a/src/cpuinfo_x86.c
+++ b/src/cpuinfo_x86.c
@@ -1,4 +1,5 @@
// Copyright 2017 Google Inc.
+// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,12 +14,13 @@
// limitations under the License.
#include "cpuinfo_x86.h"
-#include "internal/bit_utils.h"
-#include "internal/cpuid_x86.h"
#include <stdbool.h>
#include <string.h>
+#include "internal/bit_utils.h"
+#include "internal/cpuid_x86.h"
+
#if !defined(CPU_FEATURES_ARCH_X86)
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
#endif
@@ -91,6 +93,8 @@ static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) {
#define MASK_MASKREG 0x20
#define MASK_ZMM0_15 0x40
#define MASK_ZMM16_31 0x80
+#define MASK_XTILECFG 0x20000
+#define MASK_XTILEDATA 0x40000
static bool HasMask(uint32_t value, uint32_t mask) {
return (value & mask) == mask;
@@ -115,6 +119,42 @@ static bool HasZmmOsXSave(uint32_t xcr0_eax) {
MASK_ZMM16_31);
}
+// Checks that operating system saves and restores AMX/TMUL state during context
+// switches.
+static bool HasTmmOsXSave(uint32_t xcr0_eax) {
+ return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
+ MASK_ZMM16_31 | MASK_XTILECFG | MASK_XTILEDATA);
+}
+
+static bool HasSecondFMA(uint32_t model) {
+ // Skylake server
+ if (model == 0x55) {
+ char proc_name[49] = {0};
+ FillX86BrandString(proc_name);
+ // detect Xeon
+ if (proc_name[9] == 'X') {
+ // detect Silver or Bronze
+ if (proc_name[17] == 'S' || proc_name[17] == 'B') return false;
+ // detect Gold 5_20 and below, except for Gold 53__
+ if (proc_name[17] == 'G' && proc_name[22] == '5')
+ return ((proc_name[23] == '3') ||
+ (proc_name[24] == '2' && proc_name[25] == '2'));
+ // detect Xeon W 210x
+ if (proc_name[17] == 'W' && proc_name[21] == '0') return false;
+ // detect Xeon D 2xxx
+ if (proc_name[17] == 'D' && proc_name[19] == '2' && proc_name[20] == '1')
+ return false;
+ }
+ return true;
+ }
+ // Cannon Lake client
+ if (model == 0x66) return false;
+ // Ice Lake client
+ if (model == 0x7d || model == 0x7e) return false;
+ // This is the right default...
+ return true;
+}
+
static void SetVendor(const Leaf leaf, char* const vendor) {
*(uint32_t*)(vendor) = leaf.ebx;
*(uint32_t*)(vendor + 4) = leaf.edx;
@@ -131,345 +171,859 @@ static int IsVendor(const Leaf leaf, const char* const name) {
static const CacheLevelInfo kEmptyCacheLevelInfo;
-static CacheLevelInfo MakeX86CacheLevelInfo(int level, CacheType cache_type,
- int cache_size, int ways,
- int line_size, int entries,
- int partitioning) {
- CacheLevelInfo info;
- info.level = level;
- info.cache_type = cache_type;
- info.cache_size = cache_size;
- info.ways = ways;
- info.line_size = line_size;
- info.tlb_entries = entries;
- info.partitioning = partitioning;
- return info;
-}
-
static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
const int UNDEF = -1;
const int KiB = 1024;
const int MiB = 1024 * KiB;
- const int GiB = 1024 * MiB;
switch (reg) {
case 0x01:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 32, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
case 0x02:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 0xFF,
- UNDEF, 2, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 2,
+ .partitioning = 0};
case 0x03:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0x04:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
- UNDEF, 8, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
case 0x05:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
- UNDEF, 32, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
case 0x06:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 8 * KiB, 4,
- 32, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 8 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x08:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
- 4, 32, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x09:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
- 4, 64, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x0A:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 2, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * KiB,
+ .ways = 2,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x0B:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
- UNDEF, 4, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 4,
+ .partitioning = 0};
case 0x0C:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x0D:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x0E:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 24 * KiB, 6, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 24 * KiB,
+ .ways = 6,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x1D:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 2, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 2,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x21:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x22:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x23:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x24:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x25:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x29:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x2C:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x30:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
- 8, 64, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x40:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DATA, UNDEF, UNDEF,
- UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = UNDEF,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x41:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x42:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x43:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x44:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x45:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x46:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x47:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x48:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 3 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x49:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case (0x49 | (1 << 8)):
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4A:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4B:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4C:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 12, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 12 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4D:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 16 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4E:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 6 * MiB, 24, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x4F:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 32, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
case 0x50:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0x51:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 128, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
case 0x52:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 256, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
case 0x55:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
- UNDEF, 7, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 7,
+ .partitioning = 0};
case 0x56:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
- UNDEF, 16, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
case 0x57:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 16, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
case 0x59:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
- UNDEF, 16, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
case 0x5A:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
- UNDEF, 32, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
case 0x5B:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0x5C:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
- UNDEF, 128, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
case 0x5D:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4, UNDEF,
- UNDEF, 256, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
case 0x60:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x61:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
- UNDEF, 48, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 48,
+ .partitioning = 0};
case 0x63:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
- UNDEF, 4, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 4,
+ .partitioning = 0};
case 0x66:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x67:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x68:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 32 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x70:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 12 * KiB,
- 8, UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 12 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x71:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
- 8, UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 16 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x72:
- return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
- 8, UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x76:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
- UNDEF, 8, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
case 0x78:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x79:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x7A:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x7B:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x7C:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
- UNDEF, 2);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
case 0x7D:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x7F:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 2, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 2,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x80:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x82:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x83:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x84:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x85:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x86:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0x87:
- return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xA0:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 0xFF,
- UNDEF, 32, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DTLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
case 0xB0:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 128, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
case 0xB1:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
- UNDEF, 8, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
case 0xB2:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0xB3:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 128, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
case 0xB4:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 256, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
case 0xB5:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0xB6:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
- UNDEF, 128, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
case 0xBA:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 64, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
case 0xC0:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
- UNDEF, 8, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
case 0xC1:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 8,
- UNDEF, 1024, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 1024,
+ .partitioning = 0};
case 0xC2:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 4,
- UNDEF, 16, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DTLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
case 0xC3:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 6,
- UNDEF, 1536, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 6,
+ .line_size = UNDEF,
+ .tlb_entries = 1536,
+ .partitioning = 0};
case 0xCA:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 4,
- UNDEF, 512, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 512,
+ .partitioning = 0};
case 0xD0:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xD1:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xD2:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xD6:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xD7:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xD8:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xDC:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * 1536 * KiB,
- 12, 64, UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * 1536 * KiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xDD:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 3 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xDE:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xE2:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xE3:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xE4:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xEA:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 24, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 12 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xEB:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 18 * MiB, 24, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 18 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xEC:
- return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 24 * MiB, 24, 64,
- UNDEF, 0);
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 24 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xF0:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 64 * KiB,
- UNDEF, UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+ .cache_size = 64 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xF1:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 128 * KiB,
- UNDEF, UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+ .cache_size = 128 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
case 0xFF:
- return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_NULL, UNDEF, UNDEF,
- UNDEF, UNDEF, 0);
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_NULL,
+ .cache_size = UNDEF,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
default:
return kEmptyCacheLevelInfo;
}
@@ -485,15 +1039,15 @@ static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
for (int i = 0; i < 4; ++i) {
- if (registers[i] & (1 << 31)) {
+ if (registers[i] & (1U << 31)) {
continue; // register does not contains valid information
}
uint32_t bytes[4];
GetByteArrayFromRegister(bytes, registers[i]);
- for (int i = 0; i < 4; ++i) {
- if (bytes[i] == 0xFF)
+ for (int j = 0; j < 4; ++j) {
+ if (bytes[j] == 0xFF)
break; // leaf 4 should be used to fetch cache information
- info->levels[info->size] = GetCacheLevelInfo(bytes[i]);
+ info->levels[info->size] = GetCacheLevelInfo(bytes[j]);
}
info->size++;
}
@@ -512,25 +1066,42 @@ static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
- int entries = leaf.ecx + 1;
- int cache_size = (ways * partitioning * line_size * (entries));
- info->levels[cache_id] = MakeX86CacheLevelInfo(
- level, cache_type, cache_size, ways, line_size, entries, partitioning);
+ int tlb_entries = leaf.ecx + 1;
+ int cache_size = (ways * partitioning * line_size * (tlb_entries));
+ info->levels[cache_id] = (CacheLevelInfo){.level = level,
+ .cache_type = cache_type,
+ .cache_size = cache_size,
+ .ways = ways,
+ .line_size = line_size,
+ .tlb_entries = tlb_entries,
+ .partitioning = partitioning};
info->size++;
}
}
+// Internal structure to hold the OS support for vector operations.
+// Avoid to recompute them since each call to cpuid is ~100 cycles.
+typedef struct {
+ bool have_sse;
+ bool have_avx;
+ bool have_avx512;
+ bool have_amx;
+} OsSupport;
+
// Reference https://en.wikipedia.org/wiki/CPUID.
-static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info) {
+static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
+ OsSupport* os_support) {
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;
- const bool have_sse_os_support = HasXmmOsXSave(xcr0_eax);
- const bool have_avx_os_support = HasYmmOsXSave(xcr0_eax);
- const bool have_avx512_os_support = HasZmmOsXSave(xcr0_eax);
+ 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);
@@ -571,7 +1142,7 @@ 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 (have_sse_os_support) {
+ if (os_support->have_sse) {
features->sse = IsBitSet(leaf_1.edx, 25);
features->sse2 = IsBitSet(leaf_1.edx, 26);
features->sse3 = IsBitSet(leaf_1.ecx, 0);
@@ -580,13 +1151,13 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info) {
features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
}
- if (have_avx_os_support) {
+ 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 (have_avx512_os_support) {
+ 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);
@@ -602,19 +1173,54 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info) {
features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
+ features->avx512_second_fma = HasSecondFMA(info->model);
+ features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3);
+ features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5);
+ features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8);
+ }
+
+ if (os_support->have_amx) {
+ features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
+ features->amx_tile = IsBitSet(leaf_7.edx, 24);
+ features->amx_int8 = IsBitSet(leaf_7.edx, 25);
+ }
+}
+
+// Reference
+// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
+static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) {
+ const Leaf leaf_80000000 = CpuId(0x80000000);
+ const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
+ const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
+
+ X86Features* const features = &info->features;
+
+ if (os_support.have_sse) {
+ features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
+ }
+
+ if (os_support.have_avx) {
+ features->fma4 = IsBitSet(leaf_80000001.ecx, 16);
}
}
static const X86Info kEmptyX86Info;
+static const OsSupport kEmptyOsSupport;
static const CacheInfo kEmptyCacheInfo;
X86Info GetX86Info(void) {
X86Info info = kEmptyX86Info;
+ OsSupport os_support = kEmptyOsSupport;
const Leaf leaf_0 = CpuId(0);
- const uint32_t max_cpuid_leaf = leaf_0.eax;
+ const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
+ const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
SetVendor(leaf_0, info.vendor);
- if (IsVendor(leaf_0, "GenuineIntel") || IsVendor(leaf_0, "AuthenticAMD")) {
- ParseCpuId(max_cpuid_leaf, &info);
+ 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);
}
return info;
}
@@ -690,10 +1296,42 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x06, 0x5E):
// https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
return INTEL_SKL;
+ case CPUID(0x06, 0x66):
+ // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
+ return INTEL_CNL;
+ case CPUID(0x06, 0x7D): // client
+ case CPUID(0x06, 0x7E): // client
+ case CPUID(0x06, 0x9D): // NNP-I
+ case CPUID(0x06, 0x6A): // server
+ case CPUID(0x06, 0x6C): // server
+ // https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor)
+ return INTEL_ICL;
+ case CPUID(0x06, 0x8C):
+ case CPUID(0x06, 0x8D):
+ // https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture)
+ return INTEL_TGL;
+ case CPUID(0x06, 0x8F):
+ // https://en.wikipedia.org/wiki/Sapphire_Rapids
+ return INTEL_SPR;
case CPUID(0x06, 0x8E):
+ switch (info->stepping) {
+ case 9:
+ return INTEL_KBL; // https://en.wikipedia.org/wiki/Kaby_Lake
+ case 10:
+ return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake
+ case 11:
+ return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture)
+ default:
+ return X86_UNKNOWN;
+ }
case CPUID(0x06, 0x9E):
- // https://en.wikipedia.org/wiki/Kaby_Lake
- return INTEL_KBL;
+ if (info->stepping > 9) {
+ // https://en.wikipedia.org/wiki/Coffee_Lake
+ return INTEL_CFL;
+ } else {
+ // https://en.wikipedia.org/wiki/Kaby_Lake
+ return INTEL_KBL;
+ }
default:
return X86_UNKNOWN;
}
@@ -759,6 +1397,8 @@ int GetX86FeaturesEnumValue(const X86Features* features,
return features->erms;
case X86_F16C:
return features->f16c;
+ case X86_FMA4:
+ return features->fma4;
case X86_FMA3:
return features->fma3;
case X86_VAES:
@@ -791,6 +1431,8 @@ int GetX86FeaturesEnumValue(const X86Features* features,
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:
@@ -825,6 +1467,20 @@ int GetX86FeaturesEnumValue(const X86Features* features,
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:
@@ -869,6 +1525,8 @@ const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
return "erms";
case X86_F16C:
return "f16c";
+ case X86_FMA4:
+ return "fma4";
case X86_FMA3:
return "fma3";
case X86_VAES:
@@ -901,6 +1559,8 @@ const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
return "sse4_1";
case X86_SSE4_2:
return "sse4_2";
+ case X86_SSE4A:
+ return "sse4a";
case X86_AVX:
return "avx";
case X86_AVX2:
@@ -935,6 +1595,20 @@ const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
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:
@@ -993,8 +1667,16 @@ const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
return "INTEL_KBL";
case INTEL_CFL:
return "INTEL_CFL";
+ case INTEL_WHL:
+ return "INTEL_WHL";
case INTEL_CNL:
return "INTEL_CNL";
+ case INTEL_ICL:
+ return "INTEL_ICL";
+ case INTEL_TGL:
+ return "INTEL_TGL";
+ case INTEL_SPR:
+ return "INTEL_SPR";
case AMD_HAMMER:
return "AMD_HAMMER";
case AMD_K10:
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index acda5e7..0783648 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// This program dumps current host data to the standard output.
+// Output can be text or json if the `--json` flag is passed.
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,7 +37,178 @@
#include "cpuinfo_ppc.h"
#endif
-static void PrintEscapedAscii(const char* str) {
+// Design principles
+// -----------------
+// We build a tree structure containing all the data to be displayed.
+// Then depending on the output type (text or json) we walk the tree and display
+// the data accordingly.
+
+// We use a bump allocator to allocate strings and nodes of the tree,
+// Memory is not intented to be reclaimed.
+typedef struct {
+ char* ptr;
+ size_t size;
+} BumpAllocator;
+
+char gGlobalBuffer[64 * 1024];
+BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
+ .size = sizeof(gGlobalBuffer)};
+
+static void internal_error() {
+ fputs("internal error\n", stderr);
+ exit(EXIT_FAILURE);
+}
+
+#define ALIGN 8
+
+static void assertAligned() {
+ if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
+}
+
+static void BA_Align() {
+ while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
+ --gBumpAllocator.size;
+ ++gBumpAllocator.ptr;
+ }
+ assertAligned();
+}
+
+// Update the available memory left in the BumpAllocator.
+static void* BA_Bump(size_t size) {
+ assertAligned();
+ // Align size to next 8B boundary.
+ size = (size + ALIGN - 1) / ALIGN * ALIGN;
+ if (gBumpAllocator.size < size) internal_error();
+ void* ptr = gBumpAllocator.ptr;
+ gBumpAllocator.size -= size;
+ gBumpAllocator.ptr += size;
+ return ptr;
+}
+
+// The type of the nodes in the tree.
+typedef enum {
+ NT_INVALID,
+ NT_INT,
+ NT_MAP,
+ NT_MAP_ENTRY,
+ NT_ARRAY,
+ NT_ARRAY_ELEMENT,
+ NT_STRING,
+} NodeType;
+
+// The node in the tree.
+typedef struct Node {
+ NodeType type;
+ unsigned integer;
+ const char* string;
+ struct Node* value;
+ struct Node* next;
+} Node;
+
+// Creates an initialized Node.
+static Node* BA_CreateNode(NodeType type) {
+ Node* tv = (Node*)BA_Bump(sizeof(Node));
+ assert(tv);
+ *tv = (Node){.type = type};
+ return tv;
+}
+
+// Adds an integer node.
+static Node* CreateInt(int value) {
+ Node* tv = BA_CreateNode(NT_INT);
+ tv->integer = value;
+ return tv;
+}
+
+// Adds a string node.
+// `value` must outlive the tree.
+static Node* CreateConstantString(const char* value) {
+ Node* tv = BA_CreateNode(NT_STRING);
+ tv->string = value;
+ return tv;
+}
+
+// Adds a map node.
+static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
+
+// Adds an array node.
+static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
+
+// Adds a formatted string node.
+static Node* CreatePrintfString(const char* format, ...) {
+ va_list arglist;
+ va_start(arglist, format);
+ char* const ptr = gBumpAllocator.ptr;
+ const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist);
+ va_end(arglist);
+ if (written < 0 || written >= (int)gBumpAllocator.size) internal_error();
+ return CreateConstantString((char*)BA_Bump(written));
+}
+
+// Adds a string node.
+static Node* CreateString(const char* value) {
+ return CreatePrintfString("%s", value);
+}
+
+// Adds a map entry node.
+static void AddMapEntry(Node* map, const char* key, Node* value) {
+ assert(map && map->type == NT_MAP);
+ Node* current = map;
+ while (current->next) current = current->next;
+ current->next = (Node*)BA_Bump(sizeof(Node));
+ *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value};
+}
+
+// Adds an array element node.
+static void AddArrayElement(Node* array, Node* value) {
+ assert(array && array->type == NT_ARRAY);
+ Node* current = array;
+ while (current->next) current = current->next;
+ current->next = (Node*)BA_Bump(sizeof(Node));
+ *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value};
+}
+
+static int cmp(const void* p1, const void* p2) {
+ return strcmp(*(const char* const*)p1, *(const char* const*)p2);
+}
+
+#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
+ static void AddFlags(Node* map, const FeatureType* features) { \
+ size_t i; \
+ const char* ptrs[LastEnum] = {0}; \
+ size_t count = 0; \
+ for (i = 0; i < LastEnum; ++i) { \
+ if (HasFeature(features, i)) { \
+ ptrs[count] = FeatureName(i); \
+ ++count; \
+ } \
+ } \
+ qsort((void*)ptrs, count, sizeof(char*), cmp); \
+ Node* const array = CreateArray(); \
+ for (i = 0; i < count; ++i) \
+ AddArrayElement(array, CreateConstantString(ptrs[i])); \
+ AddMapEntry(map, "flags", array); \
+ }
+
+#if defined(CPU_FEATURES_ARCH_X86)
+DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
+ X86_LAST_)
+#elif defined(CPU_FEATURES_ARCH_ARM)
+DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
+ ARM_LAST_)
+#elif defined(CPU_FEATURES_ARCH_AARCH64)
+DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
+ Aarch64Features, AARCH64_LAST_)
+#elif defined(CPU_FEATURES_ARCH_MIPS)
+DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
+ MipsFeatures, MIPS_LAST_)
+#elif defined(CPU_FEATURES_ARCH_PPC)
+DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
+ PPC_LAST_)
+#endif
+
+// Prints a json string with characters escaping.
+static void printJsonString(const char* str) {
putchar('"');
for (; str && *str; ++str) {
switch (*str) {
@@ -49,188 +227,201 @@ static void PrintEscapedAscii(const char* str) {
putchar('"');
}
-static void PrintVoid(void) {}
-static void PrintComma(void) { putchar(','); }
-static void PrintLineFeed(void) { putchar('\n'); }
-static void PrintOpenBrace(void) { putchar('{'); }
-static void PrintCloseBrace(void) { putchar('}'); }
-static void PrintOpenBracket(void) { putchar('['); }
-static void PrintCloseBracket(void) { putchar(']'); }
-static void PrintString(const char* field) { printf("%s", field); }
-static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
-static void PrintIntValue(int value) { printf("%d", value); }
-static void PrintDecHexValue(int value) {
- printf("%3d (0x%02X)", value, value);
+// Walks a Node and print it as json.
+static void printJson(const Node* current) {
+ assert(current);
+ switch (current->type) {
+ case NT_INVALID:
+ break;
+ case NT_INT:
+ printf("%d", current->integer);
+ break;
+ case NT_STRING:
+ printJsonString(current->string);
+ break;
+ case NT_ARRAY:
+ putchar('[');
+ if (current->next) printJson(current->next);
+ putchar(']');
+ break;
+ case NT_MAP:
+ putchar('{');
+ if (current->next) printJson(current->next);
+ putchar('}');
+ break;
+ case NT_MAP_ENTRY:
+ printf("\"%s\":", current->string);
+ printJson(current->value);
+ if (current->next) {
+ putchar(',');
+ printJson(current->next);
+ }
+ break;
+ case NT_ARRAY_ELEMENT:
+ printJson(current->value);
+ if (current->next) {
+ putchar(',');
+ printJson(current->next);
+ }
+ break;
+ }
}
-static void PrintJsonHeader(const char* field) {
- PrintEscapedAscii(field);
- putchar(':');
+
+// Walks a Node and print it as text.
+static void printTextField(const Node* current) {
+ switch (current->type) {
+ case NT_INVALID:
+ break;
+ case NT_INT:
+ printf("%3d (0x%02X)", current->integer, current->integer);
+ break;
+ case NT_STRING:
+ fputs(current->string, stdout);
+ break;
+ case NT_ARRAY:
+ if (current->next) printTextField(current->next);
+ break;
+ case NT_MAP:
+ if (current->next) {
+ printf("{");
+ printJson(current->next);
+ printf("}");
+ }
+ break;
+ case NT_MAP_ENTRY:
+ printf("%-15s : ", current->string);
+ printTextField(current->value);
+ if (current->next) {
+ putchar('\n');
+ printTextField(current->next);
+ }
+ break;
+ case NT_ARRAY_ELEMENT:
+ printTextField(current->value);
+ if (current->next) {
+ putchar(',');
+ printTextField(current->next);
+ }
+ break;
+ }
}
-typedef struct {
- void (*Start)(void);
- void (*ArrayStart)(void);
- void (*ArraySeparator)(void);
- void (*ArrayEnd)(void);
- void (*PrintString)(const char* value);
- void (*PrintValue)(int value);
- void (*EndField)(void);
- void (*StartField)(const char* field);
- void (*End)(void);
-} Printer;
-
-static Printer getJsonPrinter(void) {
- return (Printer){
- .Start = &PrintOpenBrace,
- .ArrayStart = &PrintOpenBracket,
- .ArraySeparator = &PrintComma,
- .ArrayEnd = &PrintCloseBracket,
- .PrintString = &PrintEscapedAscii,
- .PrintValue = &PrintIntValue,
- .EndField = &PrintComma,
- .StartField = &PrintJsonHeader,
- .End = &PrintCloseBrace,
- };
-}
-
-static Printer getTextPrinter(void) {
- return (Printer){
- .Start = &PrintVoid,
- .ArrayStart = &PrintVoid,
- .ArraySeparator = &PrintComma,
- .ArrayEnd = &PrintVoid,
- .PrintString = &PrintString,
- .PrintValue = &PrintDecHexValue,
- .EndField = &PrintLineFeed,
- .StartField = &PrintAlignedHeader,
- .End = &PrintVoid,
- };
-}
-
-// Prints a named numeric value in both decimal and hexadecimal.
-static void PrintN(const Printer p, const char* field, int value) {
- p.StartField(field);
- p.PrintValue(value);
- p.EndField();
-}
-
-// Prints a named string.
-static void PrintS(const Printer p, const char* field, const char* value) {
- p.StartField(field);
- p.PrintString(value);
- p.EndField();
+static void printTextRoot(const Node* current) {
+ if (current->type == NT_MAP && current->next) printTextField(current->next);
}
-static int cmp(const void* p1, const void* p2) {
- return strcmp(*(const char* const*)p1, *(const char* const*)p2);
+static void showUsage(const char* name) {
+ printf(
+ "\n"
+ "Usage: %s [options]\n"
+ " Options:\n"
+ " -h | --help Show help message.\n"
+ " -j | --json Format output as json instead of plain text.\n"
+ "\n",
+ name);
}
-#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
- static void PrintFlags(const Printer p, const FeatureType* features) { \
- size_t i; \
- const char* ptrs[LastEnum] = {0}; \
- size_t count = 0; \
- for (i = 0; i < LastEnum; ++i) { \
- if (HasFeature(features, i)) { \
- ptrs[count] = FeatureName(i); \
- ++count; \
- } \
- } \
- qsort((void*)ptrs, count, sizeof(char*), cmp); \
- p.StartField("flags"); \
- p.ArrayStart(); \
- for (i = 0; i < count; ++i) { \
- if (i > 0) p.ArraySeparator(); \
- p.PrintString(ptrs[i]); \
- } \
- p.ArrayEnd(); \
+static Node* GetCacheTypeString(CacheType cache_type) {
+ switch (cache_type) {
+ case CPU_FEATURE_CACHE_NULL:
+ return CreateConstantString("null");
+ case CPU_FEATURE_CACHE_DATA:
+ return CreateConstantString("data");
+ case CPU_FEATURE_CACHE_INSTRUCTION:
+ return CreateConstantString("instruction");
+ case CPU_FEATURE_CACHE_UNIFIED:
+ return CreateConstantString("unified");
+ case CPU_FEATURE_CACHE_TLB:
+ return CreateConstantString("tlb");
+ case CPU_FEATURE_CACHE_DTLB:
+ return CreateConstantString("dtlb");
+ case CPU_FEATURE_CACHE_STLB:
+ return CreateConstantString("stlb");
+ case CPU_FEATURE_CACHE_PREFETCH:
+ return CreateConstantString("prefetch");
}
+}
-#if defined(CPU_FEATURES_ARCH_X86)
-DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
- X86_LAST_)
-#elif defined(CPU_FEATURES_ARCH_ARM)
-DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
- ARM_LAST_)
-#elif defined(CPU_FEATURES_ARCH_AARCH64)
-DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
- Aarch64Features, AARCH64_LAST_)
-#elif defined(CPU_FEATURES_ARCH_MIPS)
-DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
- MipsFeatures, MIPS_LAST_)
-#elif defined(CPU_FEATURES_ARCH_PPC)
-DEFINE_PRINT_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
- PPC_LAST_)
-#endif
+static void AddCacheInfo(Node* root, const CacheInfo* cache_info) {
+ Node* array = CreateArray();
+ for (int i = 0; i < cache_info->size; ++i) {
+ CacheLevelInfo info = cache_info->levels[i];
+ Node* map = CreateMap();
+ AddMapEntry(map, "level", CreateInt(info.level));
+ AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type));
+ AddMapEntry(map, "cache_size", CreateInt(info.cache_size));
+ AddMapEntry(map, "ways", CreateInt(info.ways));
+ AddMapEntry(map, "line_size", CreateInt(info.line_size));
+ AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries));
+ AddMapEntry(map, "partitioning", CreateInt(info.partitioning));
+ AddArrayElement(array, map);
+ }
+ AddMapEntry(root, "cache_info", array);
+}
-static void PrintFeatures(const Printer printer) {
+static Node* CreateTree() {
+ Node* root = CreateMap();
#if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49];
const X86Info info = GetX86Info();
+ const CacheInfo cache_info = GetX86CacheInfo();
FillX86BrandString(brand_string);
- PrintS(printer, "arch", "x86");
- PrintS(printer, "brand", brand_string);
- PrintN(printer, "family", info.family);
- PrintN(printer, "model", info.model);
- PrintN(printer, "stepping", info.stepping);
- PrintS(printer, "uarch",
- GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
- PrintFlags(printer, &info.features);
+ AddMapEntry(root, "arch", CreateString("x86"));
+ AddMapEntry(root, "brand", CreateString(brand_string));
+ AddMapEntry(root, "family", CreateInt(info.family));
+ AddMapEntry(root, "model", CreateInt(info.model));
+ AddMapEntry(root, "stepping", CreateInt(info.stepping));
+ AddMapEntry(root, "uarch",
+ CreateString(
+ GetX86MicroarchitectureName(GetX86Microarchitecture(&info))));
+ AddFlags(root, &info.features);
+ AddCacheInfo(root, &cache_info);
#elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo();
- PrintS(printer, "arch", "ARM");
- PrintN(printer, "implementer", info.implementer);
- PrintN(printer, "architecture", info.architecture);
- PrintN(printer, "variant", info.variant);
- PrintN(printer, "part", info.part);
- PrintN(printer, "revision", info.revision);
- PrintFlags(printer, &info.features);
+ AddMapEntry(root, "arch", CreateString("ARM"));
+ AddMapEntry(root, "implementer", CreateInt(info.implementer));
+ AddMapEntry(root, "architecture", CreateInt(info.architecture));
+ AddMapEntry(root, "variant", CreateInt(info.variant));
+ AddMapEntry(root, "part", CreateInt(info.part));
+ AddMapEntry(root, "revision", CreateInt(info.revision));
+ AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info();
- PrintS(printer, "arch", "aarch64");
- PrintN(printer, "implementer", info.implementer);
- PrintN(printer, "variant", info.variant);
- PrintN(printer, "part", info.part);
- PrintN(printer, "revision", info.revision);
- PrintFlags(printer, &info.features);
+ AddMapEntry(root, "arch", CreateString("aarch64"));
+ AddMapEntry(root, "implementer", CreateInt(info.implementer));
+ AddMapEntry(root, "variant", CreateInt(info.variant));
+ AddMapEntry(root, "part", CreateInt(info.part));
+ AddMapEntry(root, "revision", CreateInt(info.revision));
+ AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS)
- (void)&PrintN; // Remove unused function warning.
const MipsInfo info = GetMipsInfo();
- PrintS(printer, "arch", "mips");
- PrintFlags(printer, &info.features);
+ AddMapEntry(root, "arch", CreateString("mips"));
+ AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_PPC)
- (void)&PrintN; // Remove unused function warning.
const PPCInfo info = GetPPCInfo();
const PPCPlatformStrings strings = GetPPCPlatformStrings();
- PrintS(printer, "arch", "ppc");
- PrintS(printer, "platform", strings.platform);
- PrintS(printer, "model", strings.model);
- PrintS(printer, "machine", strings.machine);
- PrintS(printer, "cpu", strings.cpu);
- PrintS(printer, "instruction set", strings.type.platform);
- PrintS(printer, "microarchitecture", strings.type.base_platform);
- PrintFlags(printer, &info.features);
+ AddMapEntry(root, "arch", CreateString("ppc"));
+ AddMapEntry(root, "platform", CreateString(strings.platform));
+ AddMapEntry(root, "model", CreateString(strings.model));
+ AddMapEntry(root, "machine", CreateString(strings.machine));
+ AddMapEntry(root, "cpu", CreateString(strings.cpu));
+ AddMapEntry(root, "instruction", CreateString(strings.type.platform));
+ AddMapEntry(root, "microarchitecture",
+ CreateString(strings.type.base_platform));
+ AddFlags(root, &info.features);
#endif
-}
-
-static void showUsage(const char* name) {
- printf(
- "\n"
- "Usage: %s [options]\n"
- " Options:\n"
- " -h | --help Show help message.\n"
- " -j | --json Format output as json instead of plain text.\n"
- "\n",
- name);
+ return root;
}
int main(int argc, char** argv) {
- Printer printer = getTextPrinter();
+ BA_Align();
+ const Node* const root = CreateTree();
+ bool outputJson = false;
int i = 1;
for (; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
- printer = getJsonPrinter();
+ outputJson = true;
} else {
showUsage(argv[0]);
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
@@ -238,9 +429,10 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
}
- printer.Start();
- PrintFeatures(printer);
- printer.End();
- PrintLineFeed();
+ if (outputJson)
+ printJson(root);
+ else
+ printTextRoot(root);
+ putchar('\n');
return EXIT_SUCCESS;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a744ee9..eb67ac0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,10 +2,6 @@
# libraries for tests
#
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
-
include_directories(../include)
add_definitions(-DCPU_FEATURES_TEST)
diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc
index bdb4d17..1bd0648 100644
--- a/test/cpuinfo_aarch64_test.cc
+++ b/test/cpuinfo_aarch64_test.cc
@@ -29,11 +29,63 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) {
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_FALSE(info.features.asimd);
+ EXPECT_FALSE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
+ EXPECT_FALSE(info.features.atomics);
+ EXPECT_FALSE(info.features.fphp);
+ EXPECT_FALSE(info.features.asimdhp);
+ EXPECT_FALSE(info.features.cpuid);
+ EXPECT_FALSE(info.features.asimdrdm);
+ EXPECT_FALSE(info.features.jscvt);
+ EXPECT_FALSE(info.features.fcma);
+ EXPECT_FALSE(info.features.lrcpc);
+ EXPECT_FALSE(info.features.dcpop);
+ EXPECT_FALSE(info.features.sha3);
+ EXPECT_FALSE(info.features.sm3);
+ EXPECT_FALSE(info.features.sm4);
+ EXPECT_FALSE(info.features.asimddp);
+ EXPECT_FALSE(info.features.sha512);
+ EXPECT_FALSE(info.features.sve);
+ EXPECT_FALSE(info.features.asimdfhm);
+ EXPECT_FALSE(info.features.dit);
+ EXPECT_FALSE(info.features.uscat);
+ EXPECT_FALSE(info.features.ilrcpc);
+ EXPECT_FALSE(info.features.flagm);
+ EXPECT_FALSE(info.features.ssbs);
+ EXPECT_FALSE(info.features.sb);
+ EXPECT_FALSE(info.features.paca);
+ EXPECT_FALSE(info.features.pacg);
+}
+
+TEST(CpuinfoAarch64Test, FromHardwareCap2) {
+ SetHardwareCapabilities(AARCH64_HWCAP_FP, AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
+ GetEmptyFilesystem(); // disabling /proc/cpuinfo
+ const auto info = GetAarch64Info();
+ EXPECT_TRUE(info.features.fp);
+
+ EXPECT_TRUE(info.features.sve2);
+ EXPECT_TRUE(info.features.bti);
+
+ EXPECT_FALSE(info.features.dcpodp);
+ EXPECT_FALSE(info.features.sveaes);
+ EXPECT_FALSE(info.features.svepmull);
+ EXPECT_FALSE(info.features.svebitperm);
+ EXPECT_FALSE(info.features.svesha3);
+ EXPECT_FALSE(info.features.svesm4);
+ EXPECT_FALSE(info.features.flagm2);
+ EXPECT_FALSE(info.features.frint);
+ EXPECT_FALSE(info.features.svei8mm);
+ EXPECT_FALSE(info.features.svef32mm);
+ EXPECT_FALSE(info.features.svef64mm);
+ EXPECT_FALSE(info.features.svebf16);
+ EXPECT_FALSE(info.features.i8mm);
+ EXPECT_FALSE(info.features.bf16);
+ EXPECT_FALSE(info.features.dgh);
+ EXPECT_FALSE(info.features.rng);
}
TEST(CpuinfoAarch64Test, ARMCortexA53) {
@@ -63,11 +115,55 @@ CPU revision : 3)");
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.asimd);
+ EXPECT_TRUE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.pmull);
EXPECT_TRUE(info.features.sha1);
EXPECT_TRUE(info.features.sha2);
EXPECT_TRUE(info.features.crc32);
+
+ EXPECT_FALSE(info.features.atomics);
+ EXPECT_FALSE(info.features.fphp);
+ EXPECT_FALSE(info.features.asimdhp);
+ EXPECT_FALSE(info.features.cpuid);
+ EXPECT_FALSE(info.features.asimdrdm);
+ EXPECT_FALSE(info.features.jscvt);
+ EXPECT_FALSE(info.features.fcma);
+ EXPECT_FALSE(info.features.lrcpc);
+ EXPECT_FALSE(info.features.dcpop);
+ EXPECT_FALSE(info.features.sha3);
+ EXPECT_FALSE(info.features.sm3);
+ EXPECT_FALSE(info.features.sm4);
+ EXPECT_FALSE(info.features.asimddp);
+ EXPECT_FALSE(info.features.sha512);
+ EXPECT_FALSE(info.features.sve);
+ EXPECT_FALSE(info.features.asimdfhm);
+ EXPECT_FALSE(info.features.dit);
+ EXPECT_FALSE(info.features.uscat);
+ EXPECT_FALSE(info.features.ilrcpc);
+ EXPECT_FALSE(info.features.flagm);
+ EXPECT_FALSE(info.features.ssbs);
+ EXPECT_FALSE(info.features.sb);
+ EXPECT_FALSE(info.features.paca);
+ EXPECT_FALSE(info.features.pacg);
+ EXPECT_FALSE(info.features.dcpodp);
+ EXPECT_FALSE(info.features.sve2);
+ EXPECT_FALSE(info.features.sveaes);
+ EXPECT_FALSE(info.features.svepmull);
+ EXPECT_FALSE(info.features.svebitperm);
+ EXPECT_FALSE(info.features.svesha3);
+ EXPECT_FALSE(info.features.svesm4);
+ EXPECT_FALSE(info.features.flagm2);
+ EXPECT_FALSE(info.features.frint);
+ EXPECT_FALSE(info.features.svei8mm);
+ EXPECT_FALSE(info.features.svef32mm);
+ EXPECT_FALSE(info.features.svef64mm);
+ EXPECT_FALSE(info.features.svebf16);
+ EXPECT_FALSE(info.features.i8mm);
+ EXPECT_FALSE(info.features.bf16);
+ EXPECT_FALSE(info.features.dgh);
+ EXPECT_FALSE(info.features.rng);
+ EXPECT_FALSE(info.features.bti);
}
} // namespace
diff --git a/test/cpuinfo_arm_test.cc b/test/cpuinfo_arm_test.cc
index 9ddf90f..fa92e11 100644
--- a/test/cpuinfo_arm_test.cc
+++ b/test/cpuinfo_arm_test.cc
@@ -43,6 +43,12 @@ TEST(CpuinfoArmTest, FromHardwareCap) {
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
+
+ // check some random features with EnumValue():
+ EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
+ EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
+ // out of bound EnumValue() check
+ EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
}
TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc
index 10b9624..3c80eee 100644
--- a/test/cpuinfo_x86_test.cc
+++ b/test/cpuinfo_x86_test.cc
@@ -88,7 +88,7 @@ TEST(CpuidX86Test, SandyBridge) {
EXPECT_FALSE(features.avx512bitalg);
EXPECT_FALSE(features.avx512vpopcntdq);
EXPECT_FALSE(features.avx512_4vnniw);
- EXPECT_FALSE(features.avx512_4vbmi2);
+ EXPECT_FALSE(features.avx512_4fmaps);
// All old cpu features should be set.
EXPECT_TRUE(features.aes);
EXPECT_TRUE(features.ssse3);
diff --git a/test/string_view_test.cc b/test/string_view_test.cc
index abfcc2c..0b6c7c2 100644
--- a/test/string_view_test.cc
+++ b/test/string_view_test.cc
@@ -38,6 +38,8 @@ TEST(StringViewTest, Build) {
TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
+ EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0);
+ EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
// Empty.
@@ -47,6 +49,8 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
+ EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0);
+ EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
// Empty.
@@ -56,6 +60,9 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
TEST(StringViewTest, CpuFeatures_StringView_StartsWith) {
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
+ EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test")));
+ EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st")));
+ EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
EXPECT_FALSE(
CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
@@ -68,8 +75,11 @@ TEST(StringViewTest, CpuFeatures_StringView_IsEquals) {
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
+ EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
+ EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a")));
+ EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
}
@@ -81,11 +91,49 @@ TEST(StringViewTest, CpuFeatures_StringView_PopFront) {
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
}
+TEST(StringViewTest, CpuFeatures_StringView_PopBack) {
+ EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te"));
+ EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test"));
+ EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str(""));
+ EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str(""));
+}
+
+TEST(StringViewTest, CpuFeatures_StringView_KeepFront) {
+ EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te"));
+ EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str(""));
+ EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test"));
+ EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test"));
+}
+
+TEST(StringViewTest, CpuFeatures_StringView_Front) {
+ EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a');
+ EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a');
+}
+
+TEST(StringViewTest, CpuFeatures_StringView_Back) {
+ EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e');
+ EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a');
+}
+
+TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) {
+ EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")),
+ str("first middle last"));
+ EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")),
+ str("first middle last"));
+ EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")),
+ str("first middle last"));
+ EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
+ str("first middle last"));
+}
+
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) {
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
+ EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794);
+ EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794);
+ EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
diff --git a/test/unix_features_aggregator_test.cc b/test/unix_features_aggregator_test.cc
index dd491f2..9017644 100644
--- a/test/unix_features_aggregator_test.cc
+++ b/test/unix_features_aggregator_test.cc
@@ -28,16 +28,23 @@ struct Features {
bool c = false;
};
-DECLARE_SETTER(Features, a)
-DECLARE_SETTER(Features, b)
-DECLARE_SETTER(Features, c)
+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},
- {{0b0010, 0b0000}, "b", &set_b},
- {{0b0000, 0b1100}, "c", &set_c}}};
+ 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) {
@@ -47,6 +54,8 @@ TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) {
EXPECT_FALSE(features.a);
EXPECT_FALSE(features.b);
EXPECT_FALSE(features.c);
+
+ EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features));
}
TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) {
@@ -56,6 +65,8 @@ TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) {
EXPECT_TRUE(features.a);
EXPECT_TRUE(features.b);
EXPECT_TRUE(features.c);
+
+ EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
}
TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) {
@@ -65,6 +76,10 @@ TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) {
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) {