初始化内容
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/cpuid.hpp"
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#define INFOWARE_XCR_XFEATURE_ENABLED_MASK _XCR_XFEATURE_ENABLED_MASK
|
||||
#else
|
||||
#define INFOWARE_XCR_XFEATURE_ENABLED_MASK 0
|
||||
#endif // Is MSVC
|
||||
|
||||
|
||||
static bool has_os_avx() {
|
||||
bool avxsupport = false;
|
||||
|
||||
std::int32_t cpuinfo[4];
|
||||
iware::detail::cpuid(cpuinfo, 1);
|
||||
|
||||
bool osusesxsave_restore = (cpuinfo[2] & (1 << 27)) != 0;
|
||||
bool cpusupportsavx = (cpuinfo[2] & (1 << 28)) != 0;
|
||||
|
||||
if(osusesxsave_restore && cpusupportsavx) {
|
||||
const auto xcrFeatureMask = iware::detail::xgetbv(INFOWARE_XCR_XFEATURE_ENABLED_MASK);
|
||||
avxsupport = (xcrFeatureMask & 0x06) == 0x06;
|
||||
}
|
||||
|
||||
return avxsupport;
|
||||
}
|
||||
|
||||
static bool has_os_avx_512() {
|
||||
if(!has_os_avx())
|
||||
return false;
|
||||
|
||||
const auto xcrFeatureMask = iware::detail::xgetbv(INFOWARE_XCR_XFEATURE_ENABLED_MASK);
|
||||
return (xcrFeatureMask & 0xE6) == 0xE6;
|
||||
}
|
||||
|
||||
|
||||
std::vector<iware::cpu::instruction_set_t> iware::cpu::supported_instruction_sets() {
|
||||
std::int32_t info[4];
|
||||
iware::detail::cpuid(info, 0);
|
||||
const auto idinfo = info[0];
|
||||
|
||||
iware::detail::cpuid(info, 0x80000000);
|
||||
const std::uint32_t extendedidinfo = info[0];
|
||||
|
||||
std::vector<iware::cpu::instruction_set_t> supported;
|
||||
supported.reserve(64);
|
||||
|
||||
|
||||
#define ADD_SET_IF(infoindex, bitindex, name) \
|
||||
if((info[(infoindex)] & (1 << (bitindex))) != 0) \
|
||||
supported.push_back(iware::cpu::instruction_set_t::name);
|
||||
|
||||
|
||||
if(idinfo >= 0x00000001) {
|
||||
iware::detail::cpuid(info, 0x00000001);
|
||||
|
||||
ADD_SET_IF(3, 22, mmx_extended);
|
||||
ADD_SET_IF(3, 23, mmx);
|
||||
ADD_SET_IF(3, 25, sse);
|
||||
ADD_SET_IF(3, 26, sse2);
|
||||
|
||||
ADD_SET_IF(2, 0, sse3);
|
||||
ADD_SET_IF(2, 9, ssse3);
|
||||
ADD_SET_IF(2, 19, sse41);
|
||||
ADD_SET_IF(2, 20, sse42);
|
||||
ADD_SET_IF(2, 25, aes);
|
||||
ADD_SET_IF(2, 28, fma3);
|
||||
ADD_SET_IF(2, 12, rd_rand);
|
||||
}
|
||||
|
||||
if(idinfo >= 0x00000007) {
|
||||
iware::detail::cpuid(info, 0x00000007);
|
||||
|
||||
if(has_os_avx()) {
|
||||
// Both must be present to have AVX
|
||||
ADD_SET_IF(1, 5, avx2);
|
||||
}
|
||||
ADD_SET_IF(1, 4, hle);
|
||||
|
||||
ADD_SET_IF(1, 3, bmi1);
|
||||
ADD_SET_IF(1, 8, bmi2);
|
||||
ADD_SET_IF(1, 19, adx);
|
||||
ADD_SET_IF(1, 14, mpx);
|
||||
ADD_SET_IF(1, 29, sha);
|
||||
|
||||
if(has_os_avx_512()) {
|
||||
supported.push_back(iware::cpu::instruction_set_t::avx_512);
|
||||
|
||||
ADD_SET_IF(1, 16, avx_512_f);
|
||||
ADD_SET_IF(1, 28, avx_512_cd);
|
||||
ADD_SET_IF(1, 26, avx_512_pf);
|
||||
ADD_SET_IF(1, 27, avx_512_er);
|
||||
ADD_SET_IF(1, 31, avx_512_vl);
|
||||
ADD_SET_IF(1, 30, avx_512_bw);
|
||||
ADD_SET_IF(1, 17, avx_512_dq);
|
||||
ADD_SET_IF(1, 21, avx_512_ifma);
|
||||
ADD_SET_IF(2, 1, avx_512_vbmi);
|
||||
}
|
||||
|
||||
ADD_SET_IF(2, 0, prefetch_wt1);
|
||||
}
|
||||
|
||||
if(extendedidinfo >= 0x80000001) {
|
||||
iware::detail::cpuid(info, 0x80000001);
|
||||
|
||||
ADD_SET_IF(3, 29, x64);
|
||||
ADD_SET_IF(3, 0, x87_fpu);
|
||||
ADD_SET_IF(3, 30, s3d_now);
|
||||
ADD_SET_IF(3, 31, s3d_now_extended);
|
||||
ADD_SET_IF(3, 29, x64);
|
||||
ADD_SET_IF(2, 5, bmi1);
|
||||
ADD_SET_IF(2, 6, bmi2);
|
||||
ADD_SET_IF(2, 16, adx);
|
||||
ADD_SET_IF(2, 11, mpx);
|
||||
}
|
||||
|
||||
|
||||
#undef ADD_SET_IF
|
||||
|
||||
|
||||
return supported;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
|
||||
static std::pair<const char* const*, const char* const*> instruction_set_to_names(iware::cpu::instruction_set_t set) {
|
||||
static const char* mmx[] = {"MMX"};
|
||||
static const char* threednow[] = {"3DNOW", "3DNOWEXT"};
|
||||
static const char* sse[] = {"SSE"};
|
||||
static const char* sse2[] = {"SSE2"};
|
||||
static const char* sse3[] = {"SSSE3", "SSE3"};
|
||||
static const char* avx[] = {"AVX"};
|
||||
|
||||
|
||||
#define HANDLED_CASE(iset, variable) \
|
||||
case iware::cpu::instruction_set_t::iset: \
|
||||
return {variable, variable + (sizeof(variable) / sizeof(*variable))};
|
||||
|
||||
switch(set) {
|
||||
HANDLED_CASE(s3d_now, threednow)
|
||||
HANDLED_CASE(mmx, mmx)
|
||||
HANDLED_CASE(sse, sse)
|
||||
HANDLED_CASE(sse2, sse2)
|
||||
HANDLED_CASE(sse3, sse3)
|
||||
HANDLED_CASE(avx, avx)
|
||||
|
||||
default:
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
#undef HANDLED_CASE
|
||||
}
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
const auto ises = supported_instruction_sets();
|
||||
if(std::find(ises.begin(), ises.end(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
const auto set_names = instruction_set_to_names(set);
|
||||
if(!set_names.first)
|
||||
return false;
|
||||
|
||||
auto ctl_data = iware::detail::sysctl("machdep.cpu.features");
|
||||
if(ctl_data.empty())
|
||||
return 0;
|
||||
|
||||
for(auto cur_name = std::strtok(ctl_data.data(), " \t\n"); cur_name; cur_name = std::strtok(nullptr, " \t\n"))
|
||||
if(std::any_of(set_names.first, set_names.second, [&](auto name) { return name == cur_name; }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
static std::pair<const char* const*, const char* const*> instruction_set_to_names(iware::cpu::instruction_set_t set) {
|
||||
static const char* mmx[] = {"mmx"};
|
||||
static const char* threednow[] = {"3dnow", "3dnowext"};
|
||||
static const char* sse[] = {"sse"};
|
||||
static const char* sse2[] = {"sse2"};
|
||||
static const char* sse3[] = {"ssse3", "sse3"};
|
||||
static const char* avx[] = {"avx"};
|
||||
|
||||
|
||||
#define HANDLED_CASE(iset, variable) \
|
||||
case iware::cpu::instruction_set_t::iset: \
|
||||
return {variable, variable + (sizeof(variable) / sizeof(*variable))};
|
||||
|
||||
switch(set) {
|
||||
HANDLED_CASE(s3d_now, threednow)
|
||||
HANDLED_CASE(mmx, mmx)
|
||||
HANDLED_CASE(sse, sse)
|
||||
HANDLED_CASE(sse2, sse2)
|
||||
HANDLED_CASE(sse3, sse3)
|
||||
HANDLED_CASE(avx, avx)
|
||||
|
||||
default:
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
#undef HANDLED_CASE
|
||||
}
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
const auto ises = supported_instruction_sets();
|
||||
if(std::find(ises.begin(), ises.end(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
const auto set_names = instruction_set_to_names(set);
|
||||
if(!set_names.first)
|
||||
return false;
|
||||
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo.is_open() || !cpuinfo)
|
||||
return false;
|
||||
|
||||
for(std::string tmp; std::getline(cpuinfo, tmp);)
|
||||
if(tmp.find("flags") == 0) {
|
||||
const auto colon_id = tmp.find_first_of(':');
|
||||
std::istringstream is(tmp.c_str() + colon_id + 1);
|
||||
while(is >> tmp)
|
||||
if(std::any_of(set_names.first, set_names.second, [&](auto name) { return tmp == name; }))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <algorithm>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
std::vector<iware::cpu::instruction_set_t> ises = supported_instruction_sets();
|
||||
if(std::find(ises.cbegin(), ises.cend(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
// TODO: is this necessary if we detect things with xgetbv and cpuid?
|
||||
// That is, AVX usually needs to have both OS support alongside
|
||||
DWORD feature;
|
||||
switch(set) {
|
||||
case iware::cpu::instruction_set_t::s3d_now:
|
||||
feature = PF_3DNOW_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::mmx:
|
||||
feature = PF_MMX_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse:
|
||||
feature = PF_XMMI_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse2:
|
||||
feature = PF_XMMI64_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse3:
|
||||
feature = PF_SSE3_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::avx:
|
||||
feature = PF_XMMI64_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsProcessorFeaturePresent(feature) != 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user