2021-10-13 03:25:16 +01:00
|
|
|
/*
|
2021-10-13 03:46:47 +01:00
|
|
|
* This file is part of the Aaru Data Preservation Suite.
|
2022-12-01 23:06:20 +00:00
|
|
|
* Copyright (c) 2019-2023 Natalia Portillo.
|
2021-10-13 03:46:47 +01:00
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2.1 of the
|
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2021-10-13 03:25:16 +01:00
|
|
|
|
2021-10-13 05:16:52 +01:00
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
2021-10-05 02:21:51 +01:00
|
|
|
#include "library.h"
|
2021-09-29 01:27:02 +01:00
|
|
|
#include "simd.h"
|
|
|
|
|
|
2021-09-26 19:44:47 +01:00
|
|
|
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
|
|
|
|
|
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
|
|
|
|
|
|
2021-09-26 17:37:50 +01:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#include <intrin.h>
|
|
|
|
|
#else
|
|
|
|
|
/*
|
|
|
|
|
* Newer versions of GCC and clang come with cpuid.h
|
|
|
|
|
* (ftr GCC 4.7 in Debian Wheezy has this)
|
|
|
|
|
*/
|
|
|
|
|
#include <cpuid.h>
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx)
|
|
|
|
|
{
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
unsigned int registers[4];
|
|
|
|
|
__cpuid(registers, info);
|
|
|
|
|
*eax = registers[0];
|
|
|
|
|
*ebx = registers[1];
|
|
|
|
|
*ecx = registers[2];
|
|
|
|
|
*edx = registers[3];
|
|
|
|
|
#else
|
|
|
|
|
/* GCC, clang */
|
|
|
|
|
unsigned int _eax;
|
|
|
|
|
unsigned int _ebx;
|
|
|
|
|
unsigned int _ecx;
|
|
|
|
|
unsigned int _edx;
|
|
|
|
|
__cpuid(info, _eax, _ebx, _ecx, _edx);
|
|
|
|
|
*eax = _eax;
|
|
|
|
|
*ebx = _ebx;
|
|
|
|
|
*ecx = _ecx;
|
|
|
|
|
*edx = _edx;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 22:30:57 +01:00
|
|
|
static void cpuidex(int info, int count, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx)
|
|
|
|
|
{
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
unsigned int registers[4];
|
|
|
|
|
__cpuidex(registers, info, count);
|
|
|
|
|
*eax = registers[0];
|
|
|
|
|
*ebx = registers[1];
|
|
|
|
|
*ecx = registers[2];
|
|
|
|
|
*edx = registers[3];
|
|
|
|
|
#else
|
|
|
|
|
/* GCC, clang */
|
|
|
|
|
unsigned int _eax;
|
|
|
|
|
unsigned int _ebx;
|
|
|
|
|
unsigned int _ecx;
|
|
|
|
|
unsigned int _edx;
|
|
|
|
|
__cpuid_count(info, count, _eax, _ebx, _ecx, _edx);
|
|
|
|
|
*eax = _eax;
|
|
|
|
|
*ebx = _ebx;
|
|
|
|
|
*ecx = _ecx;
|
|
|
|
|
*edx = _edx;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-26 17:37:50 +01:00
|
|
|
int have_clmul(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned eax, ebx, ecx, edx;
|
|
|
|
|
int has_pclmulqdq;
|
|
|
|
|
int has_sse41;
|
|
|
|
|
cpuid(1 /* feature bits */, &eax, &ebx, &ecx, &edx);
|
|
|
|
|
|
|
|
|
|
has_pclmulqdq = ecx & 0x2; /* bit 1 */
|
|
|
|
|
has_sse41 = ecx & 0x80000; /* bit 19 */
|
|
|
|
|
|
|
|
|
|
return has_pclmulqdq && has_sse41;
|
|
|
|
|
}
|
2021-09-26 19:44:47 +01:00
|
|
|
|
2021-09-28 20:16:40 +01:00
|
|
|
int have_ssse3(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned eax, ebx, ecx, edx;
|
|
|
|
|
cpuid(1 /* feature bits */, &eax, &ebx, &ecx, &edx);
|
|
|
|
|
|
|
|
|
|
return ecx & 0x200;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 22:30:57 +01:00
|
|
|
int have_avx2(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned eax, ebx, ecx, edx;
|
|
|
|
|
cpuidex(7 /* extended feature bits */, 0, &eax, &ebx, &ecx, &edx);
|
|
|
|
|
|
|
|
|
|
return ebx & 0x20;
|
|
|
|
|
}
|
2021-09-29 01:27:02 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
|
2021-10-13 00:41:58 +01:00
|
|
|
#if defined(_WIN32)
|
|
|
|
|
#include <windows.h>
|
2021-10-13 03:46:47 +01:00
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
#include <processthreadsapi.h>
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
#include <sys/sysctl.h>
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
2021-09-29 01:27:02 +01:00
|
|
|
#include <sys/auxv.h>
|
|
|
|
|
#endif
|
2021-10-13 00:41:58 +01:00
|
|
|
#endif
|
2021-09-29 01:27:02 +01:00
|
|
|
|
2021-10-13 03:46:47 +01:00
|
|
|
#if(defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)) && defined(__APPLE__)
|
2021-10-13 02:54:21 +01:00
|
|
|
int have_neon_apple()
|
|
|
|
|
{
|
2021-10-13 03:46:47 +01:00
|
|
|
int value;
|
2021-10-13 02:54:21 +01:00
|
|
|
size_t len = sizeof(int);
|
2021-10-13 03:46:47 +01:00
|
|
|
int ret = sysctlbyname("hw.optional.neon", &value, &len, NULL, 0);
|
2021-10-13 02:54:21 +01:00
|
|
|
|
2021-10-13 03:46:47 +01:00
|
|
|
if(ret != 0) return 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
|
|
|
|
|
return value == 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int have_crc32_apple()
|
|
|
|
|
{
|
2021-10-13 03:46:47 +01:00
|
|
|
int value;
|
2021-10-13 02:54:21 +01:00
|
|
|
size_t len = sizeof(int);
|
2022-12-02 22:29:14 +00:00
|
|
|
int ret = sysctlbyname("hw.optional.armv8_crc32", &value, &len, NULL, 0);
|
2021-10-13 02:54:21 +01:00
|
|
|
|
2021-10-13 03:46:47 +01:00
|
|
|
if(ret != 0) return 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
|
|
|
|
|
return value == 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int have_crypto_apple() { return 0; }
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-09-29 01:27:02 +01:00
|
|
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
|
|
|
|
int have_neon(void)
|
|
|
|
|
{
|
|
|
|
|
return 1; // ARMv8-A made it mandatory
|
|
|
|
|
}
|
2021-09-29 02:49:40 +01:00
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
int have_arm_crc32(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
return have_crc32_apple();
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
|
|
|
|
return getauxval(AT_HWCAP) & HWCAP_CRC32;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-10-05 00:31:37 +01:00
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
int have_arm_crypto(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
return have_crypto_apple();
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
|
|
|
|
return getauxval(AT_HWCAP) & HWCAP_AES;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-09-29 01:27:02 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__arm__) || defined(_M_ARM)
|
2021-10-13 00:41:58 +01:00
|
|
|
int have_neon(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE) != 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
return have_neon_apple();
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
|
|
|
|
return getauxval(AT_HWCAP) & HWCAP_NEON;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-09-29 02:49:40 +01:00
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
int have_arm_crc32(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
return have_crc32_apple();
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
2023-09-23 00:53:23 +01:00
|
|
|
|
|
|
|
|
// Not defined in ARMv7 compilers, even if the CPU has the capability
|
|
|
|
|
#ifndef HWCAP2_CRC32
|
|
|
|
|
#define HWCAP2_CRC32 (1 << 4)
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
return getauxval(AT_HWCAP2) & HWCAP2_CRC32;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-10-05 00:31:37 +01:00
|
|
|
|
2021-10-13 00:41:58 +01:00
|
|
|
int have_arm_crypto(void)
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;
|
2021-10-13 02:54:21 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
return have_crypto_apple();
|
2021-10-13 00:41:58 +01:00
|
|
|
#else
|
|
|
|
|
return getauxval(AT_HWCAP2) & HWCAP2_AES;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-10-13 05:16:52 +01:00
|
|
|
#endif
|