5#if (defined(__GNUC__) || defined(__clang__)) && !defined(EMSCRIPTEN) && !defined(__APPLE__)
12#include "Foundation/Logging/Logger.h"
16#include "Services/Features.h"
36#elif defined(__GNUC__) || defined(__clang__)
37 __get_cpuid(level, &eax, &ebx, &ecx, &edx);
39#error "implement cpuid for this compiler"
56 detectedCPUFeatureSet = CPUFeature::None;
59 CpuId level0(0x00000000u);
60 if ((level0.ebx == 0x756e6547u) && (level0.edx == 0x49656e69u) && (level0.ecx == 0x6c65746eu)) {
62 detectedCPUFeatureSet |= CPUFeature::Intel;
64 else if ((level0.ebx == 0x68747541u) && (level0.edx == 0x69746e65u) && (level0.ecx == 0x444d4163u)) {
66 detectedCPUFeatureSet |= CPUFeature::AMD;
73 if (1 <= level0.eax) {
74 CpuId level1(0x00000001u);
75 if (level1.edx & (1u << 25u)) {
76 detectedCPUFeatureSet |= CPUFeature::SSE;
78 if (level1.edx & (1u << 26u)) {
79 detectedCPUFeatureSet |= CPUFeature::SSE2;
81 if (level1.ecx & (1u << 0u)) {
82 detectedCPUFeatureSet |= CPUFeature::SSE3;
84 if (level1.ecx & (1u << 9u)) {
85 detectedCPUFeatureSet |= CPUFeature::SSSE3;
87 if (level1.ecx & (1u << 12u)) {
88 detectedCPUFeatureSet |= CPUFeature::FMA3;
90 if (level1.ecx & (1u << 19u)) {
91 detectedCPUFeatureSet |= CPUFeature::SSE41;
93 if (level1.ecx & (1u << 20u)) {
94 detectedCPUFeatureSet |= CPUFeature::SSE42;
96 if (level1.ecx & (1u << 22u)) {
97 detectedCPUFeatureSet |= CPUFeature::MovBE;
99 if (level1.ecx & (1u << 23u)) {
100 detectedCPUFeatureSet |= CPUFeature::PopCnt;
102 if (level1.ecx & (1u << 27u)) {
105 if (useAvx && osxsave && (level1.ecx & (1u << 28u))) {
106 detectedCPUFeatureSet |= CPUFeature::AVX;
108 if (level1.ecx & (1u << 29u)) {
109 detectedCPUFeatureSet |= CPUFeature::F16C;
112 if (7 <= level0.eax) {
113 CpuId level7(0x00000007u);
114 if (level7.ebx & (1u << 3u)) {
115 detectedCPUFeatureSet |= CPUFeature::BMI1;
117 if (level7.ebx & (1u << 8u)) {
118 detectedCPUFeatureSet |= CPUFeature::BMI2;
120 if (useAvx && osxsave && (level7.ebx & (1u << 5u))) {
121 detectedCPUFeatureSet |= CPUFeature::AVX2;
123 if (useAvx && osxsave && (level7.ebx & (1u << 16u))) {
124 detectedCPUFeatureSet |= CPUFeature::AVX512F;
126 if (useAvx && osxsave && (level7.ebx & (1u << 28u))) {
127 detectedCPUFeatureSet |= CPUFeature::AVX512CD;
129 if (useAvx && osxsave && (level7.ebx & (1u << 27u))) {
130 detectedCPUFeatureSet |= CPUFeature::AVX512ER;
132 if (useAvx && osxsave && (level7.ebx & (1u << 26u))) {
133 detectedCPUFeatureSet |= CPUFeature::AVX512PF;
135 if (useAvx && osxsave && (level7.ebx & (1u << 30u))) {
136 detectedCPUFeatureSet |= CPUFeature::AVX512BW;
138 if (useAvx && osxsave && (level7.ebx & (1u << 17u))) {
139 detectedCPUFeatureSet |= CPUFeature::AVX512DQ;
141 if (useAvx && osxsave && (level7.ebx & (1u << 31u))) {
142 detectedCPUFeatureSet |= CPUFeature::AVX512VL;
146 CpuId xLevel0(0x80000000u);
147 if (0x80000001u <= xLevel0.eax) {
148 CpuId xLevel1(0x80000001u);
149 if (xLevel1.edx & (1u << 15u)) {
150 detectedCPUFeatureSet |= CPUFeature::CMov;
152 if (xLevel1.ecx & (1u << 5u)) {
153 detectedCPUFeatureSet |= CPUFeature::PopCnt;
154 detectedCPUFeatureSet |= CPUFeature::LZCnt;
156 if (xLevel1.ecx & (1u << 11u)) {
157 detectedCPUFeatureSet |= CPUFeature::XOP;
159 if (xLevel1.ecx & (1 << 6)) {
160 detectedCPUFeatureSet |= CPUFeature::SSE4a;
162 if (xLevel1.ecx & (1 << 16)) {
163 detectedCPUFeatureSet |= CPUFeature::FMA4;
165 if (xLevel1.ecx & (1 << 21)) {
166 detectedCPUFeatureSet |= CPUFeature::TBM;
172 LOG_DEBUG(logger,
"CPU features: %s",
asString().c_str());
182 currentCPUFeatureSet = allowedSet & detectedCPUFeatureSet;
188 std::vector<std::string> v;
191 if (
supported(CPUFeature::Intel)) { v.push_back(
"Intel"); }
192 if (
supported(CPUFeature::AMD)) { v.push_back(
"AMD"); }
193 if (
supported(CPUFeature::SSE)) { v.push_back(
"SSE"); }
194 if (
supported(CPUFeature::SSE2)) { v.push_back(
"SSE2"); }
195 if (
supported(CPUFeature::SSE3)) { v.push_back(
"SSE3"); }
196 if (
supported(CPUFeature::SSSE3)) { v.push_back(
"SSSE3"); }
197 if (
supported(CPUFeature::SSE4a)) { v.push_back(
"SSE4a"); }
198 if (
supported(CPUFeature::SSE41)) { v.push_back(
"SSE41"); }
199 if (
supported(CPUFeature::SSE42)) { v.push_back(
"SSE42"); }
200 if (
supported(CPUFeature::XOP)) { v.push_back(
"XOP"); }
201 if (
supported(CPUFeature::AVX)) { v.push_back(
"AVX"); }
202 if (
supported(CPUFeature::AVX2)) { v.push_back(
"AVX2"); }
203 if (
supported(CPUFeature::AVX512F)) { v.push_back(
"AVX512F"); }
204 if (
supported(CPUFeature::AVX512CD)) { v.push_back(
"AVX512CD"); }
205 if (
supported(CPUFeature::AVX512ER)) { v.push_back(
"AVX512ER"); }
206 if (
supported(CPUFeature::AVX512PF)) { v.push_back(
"AVX512PF"); }
207 if (
supported(CPUFeature::AVX512BW)) { v.push_back(
"AVX512BW"); }
208 if (
supported(CPUFeature::AVX512DQ)) { v.push_back(
"AVX512DQ"); }
209 if (
supported(CPUFeature::AVX512VL)) { v.push_back(
"AVX512VL"); }
210 if (
supported(CPUFeature::BMI1)) { v.push_back(
"BMI1"); }
211 if (
supported(CPUFeature::BMI2)) { v.push_back(
"BMI2"); }
212 if (
supported(CPUFeature::FMA3)) { v.push_back(
"FMA3"); }
213 if (
supported(CPUFeature::FMA4)) { v.push_back(
"FMA4"); }
214 if (
supported(CPUFeature::CMov)) { v.push_back(
"CMov"); }
215 if (
supported(CPUFeature::MovBE)) { v.push_back(
"MovBE"); }
216 if (
supported(CPUFeature::PopCnt)) { v.push_back(
"PopCnt"); }
217 if (
supported(CPUFeature::LZCnt)) { v.push_back(
"LZCnt"); }
218 if (
supported(CPUFeature::TBM)) { v.push_back(
"TBM"); }
219 if (
supported(CPUFeature::F16C)) { v.push_back(
"F16C"); }
220 if (
supported(CPUFeature::ADX)) { v.push_back(
"ADX"); }
228 for (
size_t i = 0; i < v.size(); i++) {
229 o << (i == 0 ?
"" :
" ") << v[i];
void restrictTo(CPUFeature allowedSet)
Restrict the set of the detected features to the intersection with allowed features.
std::string asString() const
Create a space-seperated list of features.
bool supported(CPUFeature featureSet) const
Check if a set of features are currently supported and enabled.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept