blob: 0c10a0024f443a3fcc74127b4dbedbae7eded564 [file] [log] [blame]
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +00001/* cpu_features.c -- Processor features detection.
2 *
3 * Copyright 2018 The Chromium Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the Chromium source repository LICENSE file.
6 */
7
8#include "cpu_features.h"
9#include "zutil.h"
10
11#include <stdint.h>
12#if defined(_MSC_VER)
13#include <intrin.h>
14#elif defined(ADLER32_SIMD_SSSE3)
15#include <cpuid.h>
16#endif
17
18/* TODO(cavalcantii): remove checks for x86_flags on deflate.
19 */
20int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0;
21int ZLIB_INTERNAL arm_cpu_enable_pmull = 0;
Noel Gordonf3175582020-04-21 08:30:00 +000022int ZLIB_INTERNAL x86_cpu_enable_sse2 = 0;
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000023int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
24int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
25
Richard Townsendc2eb8a72020-02-14 01:15:01 +000026#ifndef CPU_NO_SIMD
27
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000028#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA)
29#include <pthread.h>
30#endif
31
32#if defined(ARMV8_OS_ANDROID)
33#include <cpu-features.h>
34#elif defined(ARMV8_OS_LINUX)
35#include <asm/hwcap.h>
36#include <sys/auxv.h>
37#elif defined(ARMV8_OS_FUCHSIA)
38#include <zircon/features.h>
39#include <zircon/syscalls.h>
40#include <zircon/types.h>
Hans Wennborg2a6432e2020-01-24 22:31:29 +000041#elif defined(ARMV8_OS_WINDOWS) || defined(X86_WINDOWS)
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000042#include <windows.h>
Hans Wennborg2a6432e2020-01-24 22:31:29 +000043#elif !defined(_MSC_VER)
Nico Weber51dd31c2020-01-24 20:43:07 +000044#include <pthread.h>
Hans Wennborg2a6432e2020-01-24 22:31:29 +000045#else
46#error cpu_features.c CPU feature detection in not defined for your platform
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000047#endif
48
49#if !defined(CPU_NO_SIMD) && !defined(ARM_OS_IOS)
50static void _cpu_check_features(void);
51#endif
52
53#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) || defined(X86_NOT_WINDOWS)
54static pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT;
55void ZLIB_INTERNAL cpu_check_features(void)
56{
57 pthread_once(&cpu_check_inited_once, _cpu_check_features);
58}
Hans Wennborg2a6432e2020-01-24 22:31:29 +000059#elif defined(ARMV8_OS_WINDOWS) || defined(X86_WINDOWS)
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000060static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT;
61static BOOL CALLBACK _cpu_check_features_forwarder(PINIT_ONCE once, PVOID param, PVOID* context)
62{
63 _cpu_check_features();
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +000064 return TRUE;
65}
66void ZLIB_INTERNAL cpu_check_features(void)
67{
68 InitOnceExecuteOnce(&cpu_check_inited_once, _cpu_check_features_forwarder,
69 NULL, NULL);
70}
71#endif
72
73#if (defined(__ARM_NEON__) || defined(__ARM_NEON))
74/*
75 * iOS@ARM is a special case where we always have NEON but don't check
76 * for crypto extensions.
77 */
78#ifndef ARM_OS_IOS
79/*
80 * See http://bit.ly/2CcoEsr for run-time detection of ARM features and also
81 * crbug.com/931275 for android_getCpuFeatures() use in the Android sandbox.
82 */
83static void _cpu_check_features(void)
84{
85#if defined(ARMV8_OS_ANDROID) && defined(__aarch64__)
86 uint64_t features = android_getCpuFeatures();
87 arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM64_FEATURE_CRC32);
88 arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM64_FEATURE_PMULL);
89#elif defined(ARMV8_OS_ANDROID) /* aarch32 */
90 uint64_t features = android_getCpuFeatures();
91 arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM_FEATURE_CRC32);
92 arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM_FEATURE_PMULL);
93#elif defined(ARMV8_OS_LINUX) && defined(__aarch64__)
94 unsigned long features = getauxval(AT_HWCAP);
95 arm_cpu_enable_crc32 = !!(features & HWCAP_CRC32);
96 arm_cpu_enable_pmull = !!(features & HWCAP_PMULL);
97#elif defined(ARMV8_OS_LINUX) && (defined(__ARM_NEON) || defined(__ARM_NEON__))
98 /* Query HWCAP2 for ARMV8-A SoCs running in aarch32 mode */
99 unsigned long features = getauxval(AT_HWCAP2);
100 arm_cpu_enable_crc32 = !!(features & HWCAP2_CRC32);
101 arm_cpu_enable_pmull = !!(features & HWCAP2_PMULL);
102#elif defined(ARMV8_OS_FUCHSIA)
103 uint32_t features;
104 zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &features);
105 if (rc != ZX_OK || (features & ZX_ARM64_FEATURE_ISA_ASIMD) == 0)
106 return; /* Report nothing if ASIMD(NEON) is missing */
107 arm_cpu_enable_crc32 = !!(features & ZX_ARM64_FEATURE_ISA_CRC32);
108 arm_cpu_enable_pmull = !!(features & ZX_ARM64_FEATURE_ISA_PMULL);
109#elif defined(ARMV8_OS_WINDOWS)
110 arm_cpu_enable_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
111 arm_cpu_enable_pmull = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
112#endif
113}
114#endif
115#elif defined(X86_NOT_WINDOWS) || defined(X86_WINDOWS)
116/*
117 * iOS@x86 (i.e. emulator) is another special case where we disable
118 * SIMD optimizations.
119 */
120#ifndef CPU_NO_SIMD
121/* On x86 we simply use a instruction to check the CPU features.
122 * (i.e. CPUID).
123 */
124static void _cpu_check_features(void)
125{
126 int x86_cpu_has_sse2;
127 int x86_cpu_has_ssse3;
128 int x86_cpu_has_sse42;
129 int x86_cpu_has_pclmulqdq;
130 int abcd[4];
Noel Gordonf3175582020-04-21 08:30:00 +0000131
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +0000132#ifdef _MSC_VER
133 __cpuid(abcd, 1);
134#else
135 __cpuid(1, abcd[0], abcd[1], abcd[2], abcd[3]);
136#endif
Noel Gordonf3175582020-04-21 08:30:00 +0000137
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +0000138 x86_cpu_has_sse2 = abcd[3] & 0x4000000;
139 x86_cpu_has_ssse3 = abcd[2] & 0x000200;
140 x86_cpu_has_sse42 = abcd[2] & 0x100000;
141 x86_cpu_has_pclmulqdq = abcd[2] & 0x2;
142
Noel Gordonf3175582020-04-21 08:30:00 +0000143 x86_cpu_enable_sse2 = x86_cpu_has_sse2;
144
Adenilson Cavalcanti5de00af2020-01-08 22:12:31 +0000145 x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
146
147 x86_cpu_enable_simd = x86_cpu_has_sse2 &&
148 x86_cpu_has_sse42 &&
149 x86_cpu_has_pclmulqdq;
150}
151#endif
152#endif
Noel Gordonf3175582020-04-21 08:30:00 +0000153#endif