1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
// Copyright 2013 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/CPUDetect.h"
#include <cstring>
#include <fstream>
#include <sstream>
#include <string>
#include <thread>
#if !defined(_WIN32) && !defined(__APPLE__)
#ifndef __FreeBSD__
#include <asm/hwcap.h>
#endif
#include <sys/auxv.h>
#include <unistd.h>
#endif
#include <fmt/format.h>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#ifndef WIN32
const char procfile[] = "/proc/cpuinfo";
static std::string GetCPUString()
{
const std::string marker = "Hardware\t: ";
std::string cpu_string = "Unknown";
std::string line;
std::ifstream file;
File::OpenFStream(file, procfile, std::ios_base::in);
if (!file)
return cpu_string;
while (std::getline(file, line))
{
if (line.find(marker) != std::string::npos)
{
cpu_string = line.substr(marker.length());
break;
}
}
return cpu_string;
}
#endif
CPUInfo cpu_info;
CPUInfo::CPUInfo()
{
Detect();
}
// Detects the various CPU features
void CPUInfo::Detect()
{
// Set some defaults here
HTT = false;
OS64bit = true;
CPU64bit = true;
Mode64bit = true;
vendor = CPUVendor::ARM;
bFMA = true;
bFlushToZero = true;
bAFP = false;
#ifdef __APPLE__
num_cores = std::thread::hardware_concurrency();
// M-series CPUs have all of these
bFP = true;
bASIMD = true;
bAES = true;
bSHA1 = true;
bSHA2 = true;
bCRC32 = true;
#elif defined(_WIN32)
num_cores = std::thread::hardware_concurrency();
// Windows does not provide any mechanism for querying the system registers on ARMv8, unlike Linux
// which traps the register reads and emulates them in the kernel. There are environment variables
// containing some of the CPU-specific values, which we could use for a lookup table in the
// future. For now, assume all features are present as all known devices which are Windows-on-ARM
// compatible also support these extensions.
bFP = true;
bASIMD = true;
bAES = true;
bCRC32 = true;
bSHA1 = true;
bSHA2 = true;
#else
// Get the information about the CPU
num_cores = sysconf(_SC_NPROCESSORS_CONF);
strncpy(cpu_string, GetCPUString().c_str(), sizeof(cpu_string));
#ifdef __FreeBSD__
u_long hwcaps = 0;
elf_aux_info(AT_HWCAP, &hwcaps, sizeof(u_long));
#else
unsigned long hwcaps = getauxval(AT_HWCAP);
#endif
bFP = hwcaps & HWCAP_FP;
bASIMD = hwcaps & HWCAP_ASIMD;
bAES = hwcaps & HWCAP_AES;
bCRC32 = hwcaps & HWCAP_CRC32;
bSHA1 = hwcaps & HWCAP_SHA1;
bSHA2 = hwcaps & HWCAP_SHA2;
#endif
}
// Turn the CPU info into a string we can show
std::string CPUInfo::Summarize()
{
std::string sum;
if (num_cores == 1)
sum = fmt::format("{}, 1 core", cpu_string);
else
sum = fmt::format("{}, {} cores", cpu_string, num_cores);
if (bAES)
sum += ", AES";
if (bCRC32)
sum += ", CRC32";
if (bSHA1)
sum += ", SHA1";
if (bSHA2)
sum += ", SHA2";
if (CPU64bit)
sum += ", 64-bit";
return sum;
}
|