blob: 5ebb8764cca35db2b4802a6ec109c9bb1a66b20f [file]
#ifndef OPENSSL_CRYPTO_CPU_ARMV8_FEATURE_PARSING_H
#define OPENSSL_CRYPTO_CPU_ARMV8_FEATURE_PARSING_H
#include <openssl/cpu.h>
#include <stdint.h>
#include "internal.h"
#if defined(OPENSSL_AARCH64)
BSSL_NAMESPACE_BEGIN
namespace armcap {
// Common field indices based on ARM architecture specification for
// ID_AA64ISAR0_EL1. These are indices (multiplied by 4 for the bit shift).
// Note: SHA3_FIELD_IDX 8 * 4 = 32 (ID_AA64ISAR0_EL1_SHA3_SHIFT value)
#define ID_AA64ISAR0_AES_FIELD_IDX 1 // Bits [7:4]
#define ID_AA64ISAR0_SHA1_FIELD_IDX 2 // Bits [11:8]
#define ID_AA64ISAR0_SHA2_FIELD_IDX 3 // Bits [15:12]
#define ID_AA64ISAR0_SHA3_FIELD_IDX 8 // Bits [35:32]
#define NBITS_ID_FIELD 4
// Helper function to extract a 4-bit field based on its index.
inline unsigned GetIDField(uint64_t reg, unsigned field_idx) {
// We mask with 0xf to ensure only the 4 relevant bits are returned.
return (reg >> (field_idx * NBITS_ID_FIELD)) & 0xf;
}
// The core function that converts the raw ID_AA64ISAR0 register value
// into the OR'd capability flags (ARMV8_AES, ARMV8_SHA3, etc.).
inline uint32_t ParseISAR0Flags(uint64_t isar0) {
uint32_t armcap = 0;
// AES and PMULL check
unsigned aes = GetIDField(isar0, ID_AA64ISAR0_AES_FIELD_IDX);
if (aes > 0) {
armcap |= ARMV8_AES;
}
if (aes > 1) {
armcap |= ARMV8_PMULL;
}
// SHA1 check
unsigned sha1 = GetIDField(isar0, ID_AA64ISAR0_SHA1_FIELD_IDX);
if (sha1 > 0) {
armcap |= ARMV8_SHA1;
}
// SHA256 and SHA512 check
unsigned sha2 = GetIDField(isar0, ID_AA64ISAR0_SHA2_FIELD_IDX);
if (sha2 > 0) {
armcap |= ARMV8_SHA256;
}
if (sha2 > 1) {
armcap |= ARMV8_SHA512;
}
// SHA3 (EOR3) check
unsigned sha3 = GetIDField(isar0, ID_AA64ISAR0_SHA3_FIELD_IDX);
if (sha3 > 0) {
armcap |= ARMV8_SHA3;
}
return armcap;
}
} // namespace armcap
BSSL_NAMESPACE_END
#endif // OPENSSL_AARCH64
#endif // OPENSSL_CRYPTO_CPU_ARMV8_FEATURE_PARSING_H