File indexing completed on 2026-11-07 10:37:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef XSIMD_CPU_FEATURES_ARM_HPP
0013 #define XSIMD_CPU_FEATURES_ARM_HPP
0014
0015 #include "./xsimd_config.hpp"
0016 #include "./xsimd_getauxval.hpp"
0017
0018 #include <cstddef>
0019 #include <cstdint>
0020
0021 #if XSIMD_TARGET_ARM && XSIMD_HAVE_LINUX_GETAUXVAL
0022
0023
0024
0025 #include <asm/hwcap.h>
0026 #endif
0027
0028 namespace xsimd
0029 {
0030
0031 namespace detail
0032 {
0033 using arm_reg64_t = std::uint64_t;
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 inline arm_reg64_t arm_rdvl_unsafe();
0046 }
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 class arm_cpu_features : private linux_hwcap_backend_default
0059 {
0060 public:
0061 inline bool neon() const noexcept;
0062 inline bool neon64() const noexcept;
0063 inline bool sve() const noexcept;
0064 inline std::size_t sve_size_bytes() const noexcept;
0065 inline bool i8mm() const noexcept;
0066 };
0067
0068
0069
0070
0071
0072 namespace detail
0073 {
0074 #if XSIMD_TARGET_ARM64 && (defined(__GNUC__) || defined(__clang__))
0075 __attribute__((target("arch=armv8-a+sve"))) inline arm_reg64_t arm_rdvl_unsafe()
0076 {
0077 arm_reg64_t vl;
0078 __asm__ volatile("rdvl %0, #1" : "=r"(vl));
0079 return vl;
0080 }
0081 #else
0082 inline arm_reg64_t arm_rdvl_unsafe() { return 0; }
0083 #endif
0084 }
0085
0086 inline bool arm_cpu_features::neon() const noexcept
0087 {
0088 #if XSIMD_TARGET_ARM && !XSIMD_TARGET_ARM64 && XSIMD_HAVE_LINUX_GETAUXVAL
0089 return hwcap().has_feature(HWCAP_NEON);
0090 #else
0091 return static_cast<bool>(XSIMD_WITH_NEON);
0092 #endif
0093 }
0094
0095 inline bool arm_cpu_features::neon64() const noexcept
0096 {
0097 return static_cast<bool>(XSIMD_WITH_NEON64);
0098 }
0099
0100 inline bool arm_cpu_features::sve() const noexcept
0101 {
0102 #if XSIMD_TARGET_ARM64 && XSIMD_HAVE_LINUX_GETAUXVAL
0103 return hwcap().has_feature(HWCAP_SVE);
0104 #else
0105 return false;
0106 #endif
0107 }
0108
0109 inline std::size_t arm_cpu_features::sve_size_bytes() const noexcept
0110 {
0111 if (sve())
0112 {
0113 return detail::arm_rdvl_unsafe();
0114 }
0115 return 0;
0116 }
0117
0118 inline bool arm_cpu_features::i8mm() const noexcept
0119 {
0120 #if XSIMD_TARGET_ARM64 && XSIMD_HAVE_LINUX_GETAUXVAL
0121 #ifdef HWCAP2_I8MM
0122 return hwcap2().has_feature(HWCAP2_I8MM);
0123 #else
0124
0125 return hwcap2().has_feature(1 << 13);
0126 #endif
0127 #else
0128 return false;
0129 #endif
0130 }
0131 }
0132 #endif