aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Chatelet <gchatelet@google.com>2020-10-12 11:50:35 +0200
committerGitHub <noreply@github.com>2020-10-12 09:50:35 +0000
commit9a8f04b24c9cca452b62ec1877a18f2e7678742b (patch)
tree0667f40d58849b849dd5f9432b507ff989e6cacb
parent3cc8f310d950b44cc6d2ead8057cf43330a726fd (diff)
downloadcpu_features-9a8f04b24c9cca452b62ec1877a18f2e7678742b.tar.gz
[NFC] Generate separate tables via macro (#137)
This is a non functional change, it allows: - Getting rid of `unix_features_aggregator` - Have a single blob describing the features - Fix wrong mocking of `hwcaps` Downside: abuse of macros makes the code slightly magical and harder to understand. It think it's still an improvement over the current situation as there's less repetition and less chances to get something wrong.
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/internal/hwcaps.h3
-rw-r--r--include/internal/unix_features_aggregator.h73
-rw-r--r--src/cpuinfo_aarch64.c137
-rw-r--r--src/cpuinfo_aarch64_db.inl71
-rw-r--r--src/cpuinfo_arm.c91
-rw-r--r--src/cpuinfo_arm_db.inl48
-rw-r--r--src/cpuinfo_mips.c41
-rw-r--r--src/cpuinfo_mips_db.inl24
-rw-r--r--src/cpuinfo_ppc.c112
-rw-r--r--src/cpuinfo_ppc_db.inl62
-rw-r--r--src/cpuinfo_x86.c261
-rw-r--r--src/cpuinfo_x86_db.inl81
-rw-r--r--src/define_tables.h72
-rw-r--r--src/hwcaps.c33
-rw-r--r--src/unix_features_aggregator.c53
-rw-r--r--test/CMakeLists.txt8
-rw-r--r--test/unix_features_aggregator_test.cc105
18 files changed, 473 insertions, 804 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 73e1eb4..2138601 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -114,9 +114,7 @@ setup_include_and_definitions(utils)
if(UNIX)
add_library(unix_based_hardware_detection OBJECT
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
- ${PROJECT_SOURCE_DIR}/include/internal/unix_features_aggregator.h
${PROJECT_SOURCE_DIR}/src/hwcaps.c
- ${PROJECT_SOURCE_DIR}/src/unix_features_aggregator.c
)
setup_include_and_definitions(unix_based_hardware_detection)
check_include_file(dlfcn.h HAVE_DLFCN_H)
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index 1c99e7b..62037c8 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -17,6 +17,7 @@
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
+#include <stdbool.h>
#include <stdint.h>
#include "cpu_features_macros.h"
@@ -170,6 +171,8 @@ typedef struct {
} HardwareCapabilities;
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+ const HardwareCapabilities hwcaps);
typedef struct {
char platform[64]; // 0 terminated string
diff --git a/include/internal/unix_features_aggregator.h b/include/internal/unix_features_aggregator.h
deleted file mode 100644
index 56abd6c..0000000
--- a/include/internal/unix_features_aggregator.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// CapabilityConfig provides a way to map cpu features to hardware caps and
-// /proc/cpuinfo flags. We then provide functions to update capabilities from
-// either source.
-#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
-#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
-
-#include <ctype.h>
-#include <stdint.h>
-
-#include "cpu_features_macros.h"
-#include "internal/hwcaps.h"
-#include "internal/string_view.h"
-
-CPU_FEATURES_START_CPP_NAMESPACE
-
-// Use the following macro to declare setter functions to be used in
-// CapabilityConfig.
-#define DECLARE_SETTER(FeatureType, FeatureName) \
- static void set_##FeatureName(void* const features, bool value) { \
- ((FeatureType*)features)->FeatureName = value; \
- }
-
-// Use the following macro to declare getter functions to be used in
-// CapabilityConfig.
-#define DECLARE_GETTER(FeatureType, FeatureName) \
- static int get_##FeatureName(void* const features) { \
- return ((FeatureType*)features)->FeatureName; \
- }
-
-#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \
- DECLARE_SETTER(FeatureType, FeatureName) \
- DECLARE_GETTER(FeatureType, FeatureName)
-
-// Describes the relationship between hardware caps and /proc/cpuinfo flags.
-typedef struct {
- const HardwareCapabilities hwcaps_mask;
- const char* const proc_cpuinfo_flag;
- void (*set_bit)(void* const, bool); // setter for the corresponding bit.
- int (*get_bit)(void* const); // getter for the corresponding bit.
-} CapabilityConfig;
-
-// For every config, looks into flags_line for the presence of the
-// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly.
-// Note: features is a pointer to the underlying Feature struct.
-void CpuFeatures_SetFromFlags(const size_t configs_size,
- const CapabilityConfig* configs,
- const StringView flags_line,
- void* const features);
-
-// For every config, looks into hwcaps for the presence of the feature. Calls
-// `set_bit` with true if the hardware capability is found.
-// Note: features is a pointer to the underlying Feature struct.
-void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
- const CapabilityConfig* configs,
- const HardwareCapabilities hwcaps,
- void* const features);
-
-CPU_FEATURES_END_CPP_NAMESPACE
-#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c
index 195f96f..542663b 100644
--- a/src/cpuinfo_aarch64.c
+++ b/src/cpuinfo_aarch64.c
@@ -21,115 +21,12 @@
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, aes)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sve)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dit)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sb)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, paca)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpodp)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sve2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, sveaes)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svepmull)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svebitperm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svesha3)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svesm4)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm2)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, frint)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svei8mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svef32mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svef64mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, svebf16)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, i8mm)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, bf16)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, dgh)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, rng)
-DECLARE_SETTER_AND_GETTER(Aarch64Features, bti)
-
-static const CapabilityConfig kConfigs[] = {
- // clang-format off
- [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},
- // clang-format on
-};
-
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
+#define DEFINE_TABLE_DB_FILENAME "cpuinfo_aarch64_db.inl"
+#include "define_tables.h"
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info) {
@@ -137,7 +34,10 @@ static bool HandleAarch64Line(const LineResult result,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
+ for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+ kSetters[i](&info->features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -168,17 +68,18 @@ static void FillProcCpuInfoData(Aarch64Info* const info) {
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void) {
- assert(kConfigsSize == AARCH64_LAST_);
-
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
Aarch64Info info = kEmptyAarch64Info;
FillProcCpuInfoData(&info);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < AARCH64_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -188,11 +89,11 @@ Aarch64Info GetAarch64Info(void) {
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value) {
- if (value >= kConfigsSize) return false;
- return kConfigs[value].get_bit((Aarch64Features*)features);
+ if (value >= AARCH64_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
- if (value >= kConfigsSize) return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= AARCH64_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_aarch64_db.inl b/src/cpuinfo_aarch64_db.inl
new file mode 100644
index 0000000..b3200f4
--- /dev/null
+++ b/src/cpuinfo_aarch64_db.inl
@@ -0,0 +1,71 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(FEATURE)
+// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)
+// clang-format off
+FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0)
+FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0)
+FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0)
+FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0)
+FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0)
+FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0)
+FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0)
+FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0)
+FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0)
+FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0)
+FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0)
+FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0)
+FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0)
+FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0)
+FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0)
+FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0)
+FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0)
+FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0)
+FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0)
+FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0)
+FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0)
+FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0)
+FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0)
+FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0)
+FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0)
+FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0)
+FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0)
+FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0)
+FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0)
+FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0)
+FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0)
+FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0)
+FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP)
+FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2)
+FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES)
+FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL)
+FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, AARCH64_HWCAP2_SVEBITPERM)
+FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3)
+FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4)
+FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2)
+FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT)
+FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM)
+FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM)
+FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM)
+FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16)
+FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM)
+FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16)
+FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH)
+FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG)
+FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
+// clang-format on
+#else
+#error "The FEATURE macro must be defined"
+#endif // FEATURE
diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c
index 0895a53..add38ce 100644
--- a/src/cpuinfo_arm.c
+++ b/src/cpuinfo_arm.c
@@ -22,69 +22,12 @@
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-
-DECLARE_SETTER_AND_GETTER(ArmFeatures, swp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, half)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, java)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, neon)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, tls)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, aes)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2)
-DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32)
-
-static const CapabilityConfig kConfigs[] = {
- // clang-format off
- [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},
- // clang-format on
-};
-
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
+#define DEFINE_TABLE_DB_FILENAME "cpuinfo_arm_db.inl"
+#include "define_tables.h"
typedef struct {
bool processor_reports_armv6;
@@ -106,7 +49,10 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
+ for (size_t i = 0; i < ARM_LAST_; ++i) {
+ kSetters[i](&info->features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -212,9 +158,12 @@ ArmInfo GetArmInfo(void) {
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
FillProcCpuInfoData(&info, &proc_cpu_info_data);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < ARM_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
FixErrors(&info, &proc_cpu_info_data);
@@ -226,11 +175,11 @@ ArmInfo GetArmInfo(void) {
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value) {
- if (value >= kConfigsSize) return false;
- return kConfigs[value].get_bit((ArmFeatures*)features);
+ if (value >= ARM_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
- if (value >= kConfigsSize) return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= ARM_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_arm_db.inl b/src/cpuinfo_arm_db.inl
new file mode 100644
index 0000000..3270389
--- /dev/null
+++ b/src/cpuinfo_arm_db.inl
@@ -0,0 +1,48 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(FEATURE)
+// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)
+// clang-format off
+FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0)
+FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0)
+FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0)
+FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0)
+FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0)
+FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0)
+FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0)
+FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0)
+FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0)
+FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0)
+FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0)
+FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0)
+FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0)
+FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0)
+FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0)
+FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0)
+FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0)
+FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0)
+FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0)
+FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0)
+FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0)
+FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0)
+FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES)
+FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL)
+FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1)
+FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2)
+FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
+// clang-format on
+#else
+#error "The FEATURE macro must be defined"
+#endif // FEATURE
diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c
index 055cf21..8e71a31 100644
--- a/src/cpuinfo_mips.c
+++ b/src/cpuinfo_mips.c
@@ -17,20 +17,15 @@
#include <assert.h>
#include "internal/filesystem.h"
+#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-DECLARE_SETTER_AND_GETTER(MipsFeatures, msa)
-DECLARE_SETTER_AND_GETTER(MipsFeatures, eva)
-DECLARE_SETTER_AND_GETTER(MipsFeatures, r6)
-
-static const CapabilityConfig kConfigs[] = {
- [MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa, &get_msa},
- [MIPS_EVA] = {{0, 0}, "eva", &set_eva, &get_eva},
- [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6, &get_r6},
-};
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
+#define DEFINE_TABLE_DB_FILENAME "cpuinfo_mips_db.inl"
+#include "define_tables.h"
static bool HandleMipsLine(const LineResult result,
MipsFeatures* const features) {
@@ -38,7 +33,10 @@ static bool HandleMipsLine(const LineResult result,
// See tests for an example.
if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) {
- CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features);
+ for (size_t i = 0; i < MIPS_LAST_; ++i) {
+ kSetters[i](features,
+ CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
+ }
}
}
return !result.eof;
@@ -61,17 +59,18 @@ static void FillProcCpuInfoData(MipsFeatures* const features) {
static const MipsInfo kEmptyMipsInfo;
MipsInfo GetMipsInfo(void) {
- assert(kConfigsSize == MIPS_LAST_);
-
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
MipsInfo info = kEmptyMipsInfo;
FillProcCpuInfoData(&info.features);
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < MIPS_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -80,11 +79,11 @@ MipsInfo GetMipsInfo(void) {
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value) {
- if (value >= kConfigsSize) return false;
- return kConfigs[value].get_bit((MipsFeatures*)features);
+ if (value >= MIPS_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
- if (value >= kConfigsSize) return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= MIPS_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_mips_db.inl b/src/cpuinfo_mips_db.inl
new file mode 100644
index 0000000..61edb2b
--- /dev/null
+++ b/src/cpuinfo_mips_db.inl
@@ -0,0 +1,24 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(FEATURE)
+// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)
+// clang-format off
+FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0)
+FEATURE(MIPS_EVA, eva, "eva", 0, 0)
+FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
+// clang-format on
+#else
+#error "The FEATURE macro must be defined"
+#endif // FEATURE
diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c
index 4353099..3be2935 100644
--- a/src/cpuinfo_ppc.c
+++ b/src/cpuinfo_ppc.c
@@ -22,96 +22,12 @@
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
-#include "internal/unix_features_aggregator.h"
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc32)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc64)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc601)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, altivec)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, fpu)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, mmu)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, mac_4xx)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, unifiedcache)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, spe)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, efpsingle)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, efpdouble)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, no_tb)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power4)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power5)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power5plus)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, cell)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, booke)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, smt)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, icachesnoop)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch205)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, pa6t)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, dfp)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, power6ext)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch206)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, vsx)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, pseries_perfmon_compat)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, truele)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ppcle)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch207)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, dscr)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ebb)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, isel)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, tar)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, vcrypto)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_nosc)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, arch300)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, ieee128)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, darn)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, scv)
-DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_no_suspend)
-
-static const CapabilityConfig kConfigs[] = {
- // clang-format off
- [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},
- // clang-format on
-};
-static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags and kHardwareCapabilities global tables.
+#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
+#define DEFINE_TABLE_DB_FILENAME "cpuinfo_ppc_db.inl"
+#include "define_tables.h"
static bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings) {
@@ -157,10 +73,12 @@ PPCInfo GetPPCInfo(void) {
* the auxilary vector.
*/
PPCInfo info = kEmptyPPCInfo;
-
- CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
- CpuFeatures_GetHardwareCapabilities(),
- &info.features);
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < PPC_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
return info;
}
@@ -179,11 +97,11 @@ PPCPlatformStrings GetPPCPlatformStrings(void) {
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value) {
- if (value >= kConfigsSize) return false;
- return kConfigs[value].get_bit((PPCFeatures*)features);
+ if (value >= PPC_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
- if (value >= kConfigsSize) return "unknown feature";
- return kConfigs[value].proc_cpuinfo_flag;
+ if (value >= PPC_LAST_) return "unknown feature";
+ return kCpuInfoFlags[value];
}
diff --git a/src/cpuinfo_ppc_db.inl b/src/cpuinfo_ppc_db.inl
new file mode 100644
index 0000000..eb4aaf4
--- /dev/null
+++ b/src/cpuinfo_ppc_db.inl
@@ -0,0 +1,62 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(FEATURE)
+// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)
+// clang-format off
+FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0)
+FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0)
+FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0)
+FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0)
+FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0)
+FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0)
+FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0)
+FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", PPC_FEATURE_UNIFIED_CACHE, 0)
+FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0)
+FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, 0)
+FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, 0)
+FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0)
+FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0)
+FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0)
+FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0)
+FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0)
+FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0)
+FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0)
+FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0)
+FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0)
+FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0)
+FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0)
+FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0)
+FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0)
+FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0)
+FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0)
+FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0)
+FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0)
+FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07)
+FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM)
+FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR)
+FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB)
+FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL)
+FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR)
+FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO)
+FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC)
+FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00)
+FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128)
+FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN)
+FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV)
+FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, PPC_FEATURE2_HTM_NO_SUSPEND)
+// clang-format on
+#else
+#error "The FEATURE macro must be defined"
+#endif // FEATURE
diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c
index 9254413..09c707a 100644
--- a/src/cpuinfo_x86.c
+++ b/src/cpuinfo_x86.c
@@ -25,6 +25,13 @@
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
#endif
+// Generation of feature's getters/setters functions and kGetters, kSetters,
+// kCpuInfoFlags global tables.
+#define DEFINE_TABLE_FEATURE_TYPE X86Features
+#define DEFINE_TABLE_DB_FILENAME "cpuinfo_x86_db.inl"
+#define DEFINE_TABLE_DONT_GENERATE_HWCAPS
+#include "define_tables.h"
+
// The following includes are necessary to provide SSE detections on pre-AVX
// microarchitectures.
#if defined(CPU_FEATURES_OS_WINDOWS)
@@ -1486,259 +1493,13 @@ void FillX86BrandString(char brand_string[49]) {
int GetX86FeaturesEnumValue(const X86Features* features,
X86FeaturesEnum value) {
- switch (value) {
- case X86_FPU:
- return features->fpu;
- case X86_TSC:
- return features->tsc;
- case X86_CX8:
- return features->cx8;
- case X86_CLFSH:
- return features->clfsh;
- case X86_MMX:
- return features->mmx;
- case X86_AES:
- return features->aes;
- case X86_ERMS:
- return features->erms;
- case X86_F16C:
- return features->f16c;
- case X86_FMA4:
- return features->fma4;
- case X86_FMA3:
- return features->fma3;
- case X86_VAES:
- return features->vaes;
- case X86_VPCLMULQDQ:
- return features->vpclmulqdq;
- case X86_BMI1:
- return features->bmi1;
- case X86_HLE:
- return features->hle;
- case X86_BMI2:
- return features->bmi2;
- case X86_RTM:
- return features->rtm;
- case X86_RDSEED:
- return features->rdseed;
- case X86_CLFLUSHOPT:
- return features->clflushopt;
- case X86_CLWB:
- return features->clwb;
- case X86_SSE:
- return features->sse;
- case X86_SSE2:
- return features->sse2;
- case X86_SSE3:
- return features->sse3;
- case X86_SSSE3:
- return features->ssse3;
- case X86_SSE4_1:
- return features->sse4_1;
- case X86_SSE4_2:
- return features->sse4_2;
- case X86_SSE4A:
- return features->sse4a;
- case X86_AVX:
- return features->avx;
- case X86_AVX2:
- return features->avx2;
- case X86_AVX512F:
- return features->avx512f;
- case X86_AVX512CD:
- return features->avx512cd;
- case X86_AVX512ER:
- return features->avx512er;
- case X86_AVX512PF:
- return features->avx512pf;
- case X86_AVX512BW:
- return features->avx512bw;
- case X86_AVX512DQ:
- return features->avx512dq;
- case X86_AVX512VL:
- return features->avx512vl;
- case X86_AVX512IFMA:
- return features->avx512ifma;
- case X86_AVX512VBMI:
- return features->avx512vbmi;
- case X86_AVX512VBMI2:
- return features->avx512vbmi2;
- case X86_AVX512VNNI:
- return features->avx512vnni;
- case X86_AVX512BITALG:
- return features->avx512bitalg;
- case X86_AVX512VPOPCNTDQ:
- return features->avx512vpopcntdq;
- case X86_AVX512_4VNNIW:
- return features->avx512_4vnniw;
- case X86_AVX512_4VBMI2:
- return features->avx512_4vbmi2;
- case X86_AVX512_SECOND_FMA:
- return features->avx512_second_fma;
- case X86_AVX512_4FMAPS:
- return features->avx512_4fmaps;
- case X86_AVX512_BF16:
- return features->avx512_bf16;
- case X86_AVX512_VP2INTERSECT:
- return features->avx512_vp2intersect;
- case X86_AMX_BF16:
- return features->amx_bf16;
- case X86_AMX_TILE:
- return features->amx_tile;
- case X86_AMX_INT8:
- return features->amx_int8;
- case X86_PCLMULQDQ:
- return features->pclmulqdq;
- case X86_SMX:
- return features->smx;
- case X86_SGX:
- return features->sgx;
- case X86_CX16:
- return features->cx16;
- case X86_SHA:
- return features->sha;
- case X86_POPCNT:
- return features->popcnt;
- case X86_MOVBE:
- return features->movbe;
- case X86_RDRND:
- return features->rdrnd;
- case X86_DCA:
- return features->dca;
- case X86_SS:
- return features->ss;
- case X86_LAST_:
- break;
- }
- return false;
+ if (value >= X86_LAST_) return false;
+ return kGetters[value](features);
}
const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
- switch (value) {
- case X86_FPU:
- return "fpu";
- case X86_TSC:
- return "tsc";
- case X86_CX8:
- return "cx8";
- case X86_CLFSH:
- return "clfsh";
- case X86_MMX:
- return "mmx";
- case X86_AES:
- return "aes";
- case X86_ERMS:
- return "erms";
- case X86_F16C:
- return "f16c";
- case X86_FMA4:
- return "fma4";
- case X86_FMA3:
- return "fma3";
- case X86_VAES:
- return "vaes";
- case X86_VPCLMULQDQ:
- return "vpclmulqdq";
- case X86_BMI1:
- return "bmi1";
- case X86_HLE:
- return "hle";
- case X86_BMI2:
- return "bmi2";
- case X86_RTM:
- return "rtm";
- case X86_RDSEED:
- return "rdseed";
- case X86_CLFLUSHOPT:
- return "clflushopt";
- case X86_CLWB:
- return "clwb";
- case X86_SSE:
- return "sse";
- case X86_SSE2:
- return "sse2";
- case X86_SSE3:
- return "sse3";
- case X86_SSSE3:
- return "ssse3";
- case X86_SSE4_1:
- return "sse4_1";
- case X86_SSE4_2:
- return "sse4_2";
- case X86_SSE4A:
- return "sse4a";
- case X86_AVX:
- return "avx";
- case X86_AVX2:
- return "avx2";
- case X86_AVX512F:
- return "avx512f";
- case X86_AVX512CD:
- return "avx512cd";
- case X86_AVX512ER:
- return "avx512er";
- case X86_AVX512PF:
- return "avx512pf";
- case X86_AVX512BW:
- return "avx512bw";
- case X86_AVX512DQ:
- return "avx512dq";
- case X86_AVX512VL:
- return "avx512vl";
- case X86_AVX512IFMA:
- return "avx512ifma";
- case X86_AVX512VBMI:
- return "avx512vbmi";
- case X86_AVX512VBMI2:
- return "avx512vbmi2";
- case X86_AVX512VNNI:
- return "avx512vnni";
- case X86_AVX512BITALG:
- return "avx512bitalg";
- case X86_AVX512VPOPCNTDQ:
- return "avx512vpopcntdq";
- case X86_AVX512_4VNNIW:
- return "avx512_4vnniw";
- case X86_AVX512_4VBMI2:
- return "avx512_4vbmi2";
- case X86_AVX512_SECOND_FMA:
- return "avx512_second_fma";
- case X86_AVX512_4FMAPS:
- return "avx512_4fmaps";
- case X86_AVX512_BF16:
- return "avx512_bf16";
- case X86_AVX512_VP2INTERSECT:
- return "avx512_vp2intersect";
- case X86_AMX_BF16:
- return "amx_bf16";
- case X86_AMX_TILE:
- return "amx_tile";
- case X86_AMX_INT8:
- return "amx_int8";
- case X86_PCLMULQDQ:
- return "pclmulqdq";
- case X86_SMX:
- return "smx";
- case X86_SGX:
- return "sgx";
- case X86_CX16:
- return "cx16";
- case X86_SHA:
- return "sha";
- case X86_POPCNT:
- return "popcnt";
- case X86_MOVBE:
- return "movbe";
- case X86_RDRND:
- return "rdrnd";
- case X86_DCA:
- return "dca";
- case X86_SS:
- return "ss";
- case X86_LAST_:
- break;
- }
- return "unknown_feature";
+ if (value >= X86_LAST_) return "unknown_feature";
+ return kCpuInfoFlags[value];
}
const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
diff --git a/src/cpuinfo_x86_db.inl b/src/cpuinfo_x86_db.inl
new file mode 100644
index 0000000..3ea280d
--- /dev/null
+++ b/src/cpuinfo_x86_db.inl
@@ -0,0 +1,81 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if defined(FEATURE)
+// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2)
+// clang-format off
+FEATURE(X86_FPU, fpu, "fpu", 0, 0)
+FEATURE(X86_TSC, tsc, "tsc", 0, 0)
+FEATURE(X86_CX8, cx8, "cx8", 0, 0)
+FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0)
+FEATURE(X86_MMX, mmx, "mmx", 0, 0)
+FEATURE(X86_AES, aes, "aes", 0, 0)
+FEATURE(X86_ERMS, erms, "erms", 0, 0)
+FEATURE(X86_F16C, f16c, "f16c", 0, 0)
+FEATURE(X86_FMA4, fma4, "fma4", 0, 0)
+FEATURE(X86_FMA3, fma3, "fma3", 0, 0)
+FEATURE(X86_VAES, vaes, "vaes", 0, 0)
+FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0)
+FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0)
+FEATURE(X86_HLE, hle, "hle", 0, 0)
+FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0)
+FEATURE(X86_RTM, rtm, "rtm", 0, 0)
+FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0)
+FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0)
+FEATURE(X86_CLWB, clwb, "clwb", 0, 0)
+FEATURE(X86_SSE, sse, "sse", 0, 0)
+FEATURE(X86_SSE2, sse2, "sse2", 0, 0)
+FEATURE(X86_SSE3, sse3, "sse3", 0, 0)
+FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0)
+FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0)
+FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0)
+FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0)
+FEATURE(X86_AVX, avx, "avx", 0, 0)
+FEATURE(X86_AVX2, avx2, "avx2", 0, 0)
+FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0)
+FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0)
+FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0)
+FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0)
+FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0)
+FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0)
+FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0)
+FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0)
+FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0)
+FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0)
+FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0)
+FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0)
+FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0)
+FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0)
+FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0)
+FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0)
+FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0)
+FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0)
+FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", 0, 0)
+FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0)
+FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0)
+FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0)
+FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0)
+FEATURE(X86_SMX, smx, "smx", 0, 0)
+FEATURE(X86_SGX, sgx, "sgx", 0, 0)
+FEATURE(X86_CX16, cx16, "cx16", 0, 0)
+FEATURE(X86_SHA, sha, "sha", 0, 0)
+FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0)
+FEATURE(X86_MOVBE, movbe, "movbe", 0, 0)
+FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0)
+FEATURE(X86_DCA, dca, "dca", 0, 0)
+FEATURE(X86_SS, ss, "ss", 0, 0)
+// clang-format on
+#else
+#error "The FEATURE macro must be defined"
+#endif // FEATURE
diff --git a/src/define_tables.h b/src/define_tables.h
new file mode 100644
index 0000000..cb5ff37
--- /dev/null
+++ b/src/define_tables.h
@@ -0,0 +1,72 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The following preprocessor constants must be defined before including this
+// file:
+// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
+// - DEFINE_TABLE_DB_FILENAME, the db file (e.g. "cpuinfo_x86_db.inl")
+
+// This file is to be included once per `cpuinfo_XXX.c` in order to construct
+// feature getters and setters functions as well as several enum indexed tables
+// from the db file.
+// - `kGetters` a table of getters function pointers from feature enum to
+// retrieve a feature,
+// - `kSetters` a table of setters function pointers from feature enum to set a
+// feature,
+// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
+// flags,
+// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
+// their feature enum.
+
+#ifndef SRC_DEFINE_TABLES_H_
+#define SRC_DEFINE_TABLES_H_
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
+static const char* kCpuInfoFlags[] = {
+#include DEFINE_TABLE_DB_FILENAME
+};
+#undef FEATURE
+
+#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
+ [ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
+static const HardwareCapabilities kHardwareCapabilities[] = {
+#include DEFINE_TABLE_DB_FILENAME
+};
+#undef FEATURE
+#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
+ static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) { \
+ features->NAME = value; \
+ } \
+ static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) { \
+ return features->NAME; \
+ }
+#include DEFINE_TABLE_DB_FILENAME
+#undef FEATURE
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
+static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*, bool) = {
+#include DEFINE_TABLE_DB_FILENAME
+};
+#undef FEATURE
+
+#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
+static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
+#include DEFINE_TABLE_DB_FILENAME
+};
+#undef FEATURE
+
+#endif // SRC_DEFINE_TABLES_H_
diff --git a/src/hwcaps.c b/src/hwcaps.c
index 1592d17..dd17e3b 100644
--- a/src/hwcaps.c
+++ b/src/hwcaps.c
@@ -21,6 +21,24 @@
#include "internal/filesystem.h"
#include "internal/string_view.h"
+static bool IsSet(const uint32_t mask, const uint32_t value) {
+ if (mask == 0) return false;
+ return (value & mask) == mask;
+}
+
+bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
+ const HardwareCapabilities hwcaps) {
+ return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
+ IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
+}
+
+#ifdef CPU_FEATURES_TEST
+// In test mode, hwcaps_for_testing will define the following functions.
+HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
+PlatformType CpuFeatures_GetPlatformType(void);
+#else
+
+// Debug facilities
#if defined(NDEBUG)
#define D(...)
#else
@@ -36,9 +54,12 @@
// Implementation of GetElfHwcapFromGetauxval
////////////////////////////////////////////////////////////////////////////////
-#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
-// Implementation will be provided by test/hwcaps_for_testing.cc.
-#elif defined(HAVE_STRONG_GETAUXVAL)
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+#define AT_PLATFORM 15
+#define AT_BASE_PLATFORM 24
+
+#if defined(HAVE_STRONG_GETAUXVAL)
#include <sys/auxv.h>
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
return getauxval(hwcap_type);
@@ -60,10 +81,6 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
// initialization layer.
#include <dlfcn.h>
-#define AT_HWCAP 16
-#define AT_HWCAP2 26
-#define AT_PLATFORM 15
-#define AT_BASE_PLATFORM 24
typedef unsigned long getauxval_func_t(unsigned long);
@@ -161,3 +178,5 @@ PlatformType CpuFeatures_GetPlatformType(void) {
sizeof(type.base_platform));
return type;
}
+
+#endif // CPU_FEATURES_TEST
diff --git a/src/unix_features_aggregator.c b/src/unix_features_aggregator.c
deleted file mode 100644
index cc79d14..0000000
--- a/src/unix_features_aggregator.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2017 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal/unix_features_aggregator.h"
-
-#include "internal/string_view.h"
-
-void CpuFeatures_SetFromFlags(const size_t configs_size,
- const CapabilityConfig* configs,
- const StringView flags_line,
- void* const features) {
- size_t i = 0;
- for (; i < configs_size; ++i) {
- const CapabilityConfig config = configs[i];
- config.set_bit(features, CpuFeatures_StringView_HasWord(
- flags_line, config.proc_cpuinfo_flag));
- }
-}
-
-static bool IsSet(const uint32_t mask, const uint32_t value) {
- if (mask == 0) return false;
- return (value & mask) == mask;
-}
-
-static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
- const HardwareCapabilities hwcaps) {
- return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
- IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
-}
-
-void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
- const CapabilityConfig* configs,
- const HardwareCapabilities hwcaps,
- void* const features) {
- size_t i = 0;
- for (; i < configs_size; ++i) {
- const CapabilityConfig* config = &configs[i];
- if (IsHwCapsSet(config->hwcaps_mask, hwcaps)) {
- config->set_bit(features, true);
- }
- }
-}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 834eec1..c10e617 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -12,7 +12,6 @@ add_library(filesystem_for_testing filesystem_for_testing.cc)
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
##------------------------------------------------------------------------------
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
-target_compile_definitions(hwcaps_for_testing PUBLIC CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(stack_line_reader ../src/stack_line_reader.c)
@@ -23,7 +22,7 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
##------------------------------------------------------------------------------
-add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c)
+add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
#
@@ -46,11 +45,6 @@ add_executable(stack_line_reader_test stack_line_reader_test.cc)
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
##------------------------------------------------------------------------------
-## unix_features_aggregator_test
-add_executable(unix_features_aggregator_test unix_features_aggregator_test.cc)
-target_link_libraries(unix_features_aggregator_test all_libraries)
-add_test(NAME unix_features_aggregator_test COMMAND unix_features_aggregator_test)
-##------------------------------------------------------------------------------
## cpuinfo_x86_test
if(PROCESSOR_IS_X86)
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
diff --git a/test/unix_features_aggregator_test.cc b/test/unix_features_aggregator_test.cc
deleted file mode 100644
index 3a36804..0000000
--- a/test/unix_features_aggregator_test.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2017 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal/unix_features_aggregator.h"
-
-#include <array>
-
-#include "gtest/gtest.h"
-
-namespace cpu_features {
-
-namespace {
-
-struct Features {
- bool a = false;
- bool b = false;
- bool c = false;
-};
-
-enum eFeatures { TEST_a, TEST_b, TEST_c };
-
-DECLARE_SETTER_AND_GETTER(Features, a)
-DECLARE_SETTER_AND_GETTER(Features, b)
-DECLARE_SETTER_AND_GETTER(Features, c)
-
-class LinuxFeatureAggregatorTest : public testing::Test {
- public:
- const std::array<CapabilityConfig, 3> kConfigs = {
- {{{0b0001, 0b0000}, "a", &set_a, &get_a},
- {{0b0010, 0b0000}, "b", &set_b, &get_b},
- {{0b0000, 0b1100}, "c", &set_c, &get_c}}};
-};
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str(""),
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-
- EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"),
- &features);
- EXPECT_TRUE(features.a);
- EXPECT_TRUE(features.b);
- EXPECT_TRUE(features.c);
-
- EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) {
- Features features;
- CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"),
- &features);
- EXPECT_TRUE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-
- EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
- EXPECT_FALSE(kConfigs[TEST_b].get_bit(&features));
- EXPECT_FALSE(kConfigs[TEST_c].get_bit(&features));
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone) {
- HardwareCapabilities capability;
- capability.hwcaps = 0; // matches none
- capability.hwcaps2 = 0; // matches none
- Features features;
- CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_FALSE(features.b);
- EXPECT_FALSE(features.c);
-}
-
-TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet) {
- HardwareCapabilities capability;
- capability.hwcaps = 0b0010; // matches b but not a
- capability.hwcaps2 = 0b1111; // matches c
- Features features;
- CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
- &features);
- EXPECT_FALSE(features.a);
- EXPECT_TRUE(features.b);
- EXPECT_TRUE(features.c);
-}
-
-} // namespace
-} // namespace cpu_features