ManaPlus
cpu.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2013-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "utils/cpu.h"
23 
24 #include "logger.h"
25 
26 #if (defined(__amd64__) || defined(__i386__)) && defined(__GNUC__) \
27  && (GCC_VERSION >= 40800) && !defined(ANDROID)
28 // nothing
29 #elif defined(__linux__) || defined(__linux)
30 #include "utils/foreach.h"
31 #include "utils/stringutils.h"
32 #endif // (defined(__amd64__) || defined(__i386__)) && defined(__GNUC__)
33  // && (GCC_VERSION >= 40800) && !defined(ANDROID)
34 
35 #ifdef USE_SDL2
36 #include <SDL_cpuinfo.h>
37 #endif // USE_SDL2
38 
39 #include "debug.h"
40 
41 namespace
42 {
43  uint32_t mCpuFlags;
44 } // namespace
45 
47 {
48 #if (defined(__amd64__) || defined(__i386__)) && defined(__GNUC__) \
49  && (GCC_VERSION >= 40800) && !defined(ANDROID)
50  __builtin_cpu_init();
51  if (__builtin_cpu_supports ("mmx"))
53  if (__builtin_cpu_supports ("sse"))
55  if (__builtin_cpu_supports ("sse2"))
57  if (__builtin_cpu_supports ("ssse3"))
59  if (__builtin_cpu_supports ("sse4.1"))
61  if (__builtin_cpu_supports ("sse4.2"))
63  if (__builtin_cpu_supports ("avx"))
65  if (__builtin_cpu_supports ("avx2"))
67  printFlags();
68 #elif defined(__linux__) || defined(__linux)
69  FILE *file = fopen("/proc/cpuinfo", "r");
70  char buf[1001];
71  if (file == nullptr)
72  return;
73  while (fgets(buf, 1000, file) != nullptr)
74  {
75  std::string str = buf;
76  if (findFirst(str, "flags"))
77  {
78  size_t idx = str.find(':');
79  if (idx == std::string::npos)
80  continue;
81  str = str.substr(idx + 1);
82  trim(str);
83  StringVect vect;
84  splitToStringVector(vect, str, ' ');
85  FOR_EACH (StringVectCIter, it, vect)
86  {
87  const std::string &flag = *it;
88  if (flag == "mmx")
90  else if (flag == "sse")
92  else if (flag == "sse2")
94  else if (flag == "ssse3")
96  else if (flag == "sse4_1")
98  else if (flag == "sse4_2")
100  else if (flag == "avx")
102  else if (flag == "avx2")
104  }
105  fclose(file);
106  printFlags();
107  return;
108  }
109  }
110  fclose(file);
111  if (logger != nullptr)
112  logger->log("cpu features was not detected");
113 #else // OTHER
114 
115 #ifdef USE_SDL2
116  if (SDL_HasMMX())
118  if (SDL_HasSSE())
120  if (SDL_HasSSE2())
122  if (SDL_HasSSE3())
124  if (SDL_HasSSE41())
126  if (SDL_HasSSE42())
128 
129 #if SDL_VERSION_ATLEAST(2, 0, 2)
130  if (SDL_HasAVX())
132 #endif // SDL_VERSION_ATLEAST(2, 0, 2)
133 #if SDL_VERSION_ATLEAST(2, 0, 4)
134  if (SDL_HasAVX2())
136 #endif // SDL_VERSION_ATLEAST(2, 0, 4)
137 
138  printFlags();
139 #else // USE_SDL2
140 
141  if (logger)
142  logger->log("cpu features not supported");
143 #endif // USE_SDL2
144 #endif // (defined(__amd64__) || defined(__i386__)) && defined(__GNUC__)
145  // && (GCC_VERSION >= 40800) && !defined(ANDROID)
146 
147 #if SDL_VERSION_ATLEAST(2, 0, 1)
148  logger->log("System ram size: %d", SDL_GetSystemRAM());
149 #endif // SDL_VERSION_ATLEAST(2, 0, 1)
150 }
151 
153 {
154  if (logger == nullptr)
155  return;
156  std::string str("CPU features:");
157  if ((mCpuFlags & FEATURE_MMX) != 0U)
158  str.append(" mmx");
159  if ((mCpuFlags & FEATURE_SSE) != 0U)
160  str.append(" sse");
161  if ((mCpuFlags & FEATURE_SSE2) != 0U)
162  str.append(" sse2");
163  if ((mCpuFlags & FEATURE_SSSE3) != 0U)
164  str.append(" ssse3");
165  if ((mCpuFlags & FEATURE_SSE4) != 0U)
166  str.append(" sse4");
167  if ((mCpuFlags & FEATURE_SSE42) != 0U)
168  str.append(" sse4_2");
169  if ((mCpuFlags & FEATURE_AVX) != 0U)
170  str.append(" avx");
171  if ((mCpuFlags & FEATURE_AVX2) != 0U)
172  str.append(" avx2");
173  logger->log(str);
174 }
175 
176 uint32_t Cpu::getFlags()
177 {
178  return mCpuFlags;
179 }
void log(const char *const log_text,...)
Definition: logger.cpp:269
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
Logger * logger
Definition: logger.cpp:89
std::string trim(std::string const &str)
uint32_t getFlags()
Definition: cpu.cpp:176
@ FEATURE_SSE42
Definition: cpu.h:37
@ FEATURE_MMX
Definition: cpu.h:32
@ FEATURE_AVX
Definition: cpu.h:38
@ FEATURE_SSE
Definition: cpu.h:33
@ FEATURE_AVX2
Definition: cpu.h:39
@ FEATURE_SSE2
Definition: cpu.h:34
@ FEATURE_SSE4
Definition: cpu.h:36
@ FEATURE_SSSE3
Definition: cpu.h:35
void printFlags()
Definition: cpu.cpp:152
void detect()
Definition: cpu.cpp:46
void splitToStringVector(StringVect &tokens, const std::string &text, const char separator)
bool findFirst(const std::string &str1, const std::string &str2)
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:31
std::vector< std::string > StringVect
Definition: stringvector.h:29