GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/utils/cpu.cpp Lines: 42 43 97.7 %
Date: 2017-11-29 Branches: 26 52 50.0 %

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