blob: e40c65a19124ff6241bab47158f48d5ff518d162 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
ajm@google.comce7c2a22011-08-04 01:50:00 +000011// Parts of this file derived from Chromium's base/cpu.cc.
12
Niels Möllera12c42a2018-07-25 16:05:48 +020013#include "rtc_base/system/arch.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "system_wrappers/include/cpu_features_wrapper.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000015
phoglund@webrtc.orgb15d2852012-11-21 08:02:57 +000016#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
ajm@google.comce7c2a22011-08-04 01:50:00 +000017#include <intrin.h>
18#endif
phoglund@webrtc.orgb15d2852012-11-21 08:02:57 +000019
Mirko Bonadeibef022b2020-09-06 16:07:15 +020020namespace webrtc {
21
niklase@google.com470e71d2011-07-07 08:21:25 +000022// No CPU feature is available => straight C path.
23int GetCPUInfoNoASM(CPUFeature feature) {
24 (void)feature;
25 return 0;
26}
27
ajm@google.comce7c2a22011-08-04 01:50:00 +000028#if defined(WEBRTC_ARCH_X86_FAMILY)
Zhaoliang Ma72e43212020-08-17 17:13:41 +080029
30#if defined(WEBRTC_ENABLE_AVX2)
31// xgetbv returns the value of an Intel Extended Control Register (XCR).
32// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
33static uint64_t xgetbv(uint32_t xcr) {
34#if defined(_MSC_VER)
35 return _xgetbv(xcr);
36#else
37 uint32_t eax, edx;
38
39 __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
40 return (static_cast<uint64_t>(edx) << 32) | eax;
41#endif // _MSC_VER
42}
43#endif // WEBRTC_ENABLE_AVX2
44
ajm@google.comce7c2a22011-08-04 01:50:00 +000045#ifndef _MSC_VER
niklase@google.com470e71d2011-07-07 08:21:25 +000046// Intrinsic for "cpuid".
47#if defined(__pic__) && defined(__i386__)
ajm@google.comce7c2a22011-08-04 01:50:00 +000048static inline void __cpuid(int cpu_info[4], int info_type) {
phoglund@webrtc.orgb15d2852012-11-21 08:02:57 +000049 __asm__ volatile(
Karl Wiberg79eb1d92017-11-08 12:26:07 +010050 "mov %%ebx, %%edi\n"
51 "cpuid\n"
52 "xchg %%edi, %%ebx\n"
53 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
54 "=d"(cpu_info[3])
55 : "a"(info_type));
niklase@google.com470e71d2011-07-07 08:21:25 +000056}
ajm@google.comce7c2a22011-08-04 01:50:00 +000057#else
58static inline void __cpuid(int cpu_info[4], int info_type) {
Karl Wiberg79eb1d92017-11-08 12:26:07 +010059 __asm__ volatile("cpuid\n"
60 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
61 "=d"(cpu_info[3])
Zhaoliang Ma72e43212020-08-17 17:13:41 +080062 : "a"(info_type), "c"(0));
niklase@google.com470e71d2011-07-07 08:21:25 +000063}
64#endif
ajm@google.comce7c2a22011-08-04 01:50:00 +000065#endif // _MSC_VER
66#endif // WEBRTC_ARCH_X86_FAMILY
niklase@google.com470e71d2011-07-07 08:21:25 +000067
ajm@google.comce7c2a22011-08-04 01:50:00 +000068#if defined(WEBRTC_ARCH_X86_FAMILY)
niklase@google.com470e71d2011-07-07 08:21:25 +000069// Actual feature detection for x86.
Mirko Bonadeibef022b2020-09-06 16:07:15 +020070int GetCPUInfo(CPUFeature feature) {
niklase@google.com470e71d2011-07-07 08:21:25 +000071 int cpu_info[4];
ajm@google.comce7c2a22011-08-04 01:50:00 +000072 __cpuid(cpu_info, 1);
niklase@google.com470e71d2011-07-07 08:21:25 +000073 if (feature == kSSE2) {
74 return 0 != (cpu_info[3] & 0x04000000);
75 }
76 if (feature == kSSE3) {
77 return 0 != (cpu_info[2] & 0x00000001);
78 }
Zhaoliang Ma72e43212020-08-17 17:13:41 +080079#if defined(WEBRTC_ENABLE_AVX2)
Andrey Logvin082fac72020-10-01 13:38:51 +000080 if (feature == kAVX2) {
Zhaoliang Ma72e43212020-08-17 17:13:41 +080081 int cpu_info7[4];
82 __cpuid(cpu_info7, 0);
83 int num_ids = cpu_info7[0];
84 if (num_ids < 7) {
85 return 0;
86 }
87 // Interpret CPU feature information.
88 __cpuid(cpu_info7, 7);
89
90 // AVX instructions can be used when
91 // a) AVX are supported by the CPU,
92 // b) XSAVE is supported by the CPU,
93 // c) XSAVE is enabled by the kernel.
94 // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
95 // AVX2 support needs (avx_support && (cpu_info7[1] & 0x00000020) != 0;).
96 return (cpu_info[2] & 0x10000000) != 0 &&
97 (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
98 (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
99 (xgetbv(0) & 0x00000006) == 6 /* XSAVE enabled by kernel */ &&
100 (cpu_info7[1] & 0x00000020) != 0;
101 }
102#endif // WEBRTC_ENABLE_AVX2
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 return 0;
104}
105#else
106// Default to straight C for other platforms.
Mirko Bonadeibef022b2020-09-06 16:07:15 +0200107int GetCPUInfo(CPUFeature feature) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 (void)feature;
109 return 0;
110}
111#endif
112
Mirko Bonadeibef022b2020-09-06 16:07:15 +0200113} // namespace webrtc