xref: /aosp_15_r20/external/libgav1/src/utils/cpu.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2019 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/utils/cpu.h"
16 
17 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
18 #include <cpuid.h>
19 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
20 #include <immintrin.h>  // _xgetbv
21 #include <intrin.h>
22 #endif
23 
24 namespace libgav1 {
25 
26 #if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
27     defined(_M_X64)
28 namespace {
29 
30 #if defined(__GNUC__)
CpuId(int leaf,uint32_t info[4])31 void CpuId(int leaf, uint32_t info[4]) {
32   __cpuid_count(leaf, 0 /*ecx=subleaf*/, info[0], info[1], info[2], info[3]);
33 }
34 
Xgetbv()35 uint64_t Xgetbv() {
36   const uint32_t ecx = 0;  // ecx specifies the extended control register
37   uint32_t eax;
38   uint32_t edx;
39   __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(ecx));
40   return (static_cast<uint64_t>(edx) << 32) | eax;
41 }
42 #else   // _MSC_VER
43 void CpuId(int leaf, uint32_t info[4]) {
44   __cpuidex(reinterpret_cast<int*>(info), leaf, 0 /*ecx=subleaf*/);
45 }
46 
47 uint64_t Xgetbv() { return _xgetbv(0); }
48 #endif  // __GNUC__
49 
50 }  // namespace
51 
GetCpuInfo()52 uint32_t GetCpuInfo() {
53   uint32_t info[4];
54 
55   // Get the highest feature value cpuid supports
56   CpuId(0, info);
57   const int max_cpuid_value = info[0];
58   if (max_cpuid_value < 1) return 0;
59 
60   CpuId(1, info);
61   uint32_t features = 0;
62   if ((info[3] & (1 << 26)) != 0) features |= kSSE2;
63   if ((info[2] & (1 << 9)) != 0) features |= kSSSE3;
64   if ((info[2] & (1 << 19)) != 0) features |= kSSE4_1;
65 
66   // Bits 27 (OSXSAVE) & 28 (256-bit AVX)
67   if ((info[2] & (3 << 27)) == (3 << 27)) {
68     // XMM state and YMM state enabled by the OS
69     if ((Xgetbv() & 0x6) == 0x6) {
70       features |= kAVX;
71       if (max_cpuid_value >= 7) {
72         CpuId(7, info);
73         if ((info[1] & (1 << 5)) != 0) features |= kAVX2;
74       }
75     }
76   }
77 
78   return features;
79 }
80 #else
81 uint32_t GetCpuInfo() { return 0; }
82 #endif  // x86 || x86_64
83 
84 }  // namespace libgav1
85