/* SPDX-License-Identifier: GPL-3.0-or-later
*
* Microcode programmable logic matrix analyzer.
* Copyright 2015-2020 Viacheslav Ovsiienko <1801BM1@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "mcode.h"
#if defined(_WIN32) || defined(_WIN64)
static inline int get_cpuid(uint32_t *info, uint32_t leaf)
{
__cpuid(info, leaf);
return 0;
}
static inline int get_cpuid_ex(uint32_t *info, uint32_t leaf, uint32_t subleaf)
{
__cpuidex(info, leaf, subleaf);
return 0;
}
#else
#ifdef __GNUC__
#include
#include
#define _XCR_XFEATURE_ENABLED_MASK 0
static inline int get_cpuid(uint32_t *info, uint32_t leaf)
{
return __get_cpuid(leaf, info + 0, info + 1,
info + 2, info + 3);
}
static inline int get_cpuid_ex(uint32_t *info, uint32_t leaf, uint32_t subleaf)
{
__cpuid_count(leaf, subleaf, info[0], info[1], info[2], info[3]);
return 0;
}
#endif
#endif
static uint32_t simd = UINT32_MAX;
uint32_t mc_query_simd(void)
{
if (simd == UINT32_MAX) {
uint32_t cpuinfo[4] = { 0 };
simd = 0;
printf("simd:");
get_cpuid(cpuinfo, 1);
if (cpuinfo[3] & (1 << 25)) {
simd |= SIMD_SSE;
printf(" SSE");
}
if (cpuinfo[3] & (1 << 26)) {
simd |= SIMD_SSE2;
printf(" SSE2");
}
if (cpuinfo[2] & (1 << 0)) {
simd |= SIMD_SSE3;
printf(" SSE3");
}
if (cpuinfo[2] & (1 << 9)) {
simd |= SIMD_SSSE3;
printf(" SSSE3");
}
if (cpuinfo[2] & (1 << 19)) {
simd |= SIMD_SSE41;
printf(" SSE41");
}
if (cpuinfo[2] & (1 << 20)) {
simd |= SIMD_SSE42;
printf(" SSE42");
}
/*
* Checking for AVX requires 3 things:
* - CPUID indicates that the OS uses XSAVE and XRSTORE
* instructions (allowing saving YMM registers on context
* switch
* - CPUID indicates support for AVX
* XGETBV indicates the AVX registers will be saved and
* restored on context switch
*
* Note that XGETBV is only available on 686 or later CPUs, so
* the instruction needs to be conditionally run.
*/
if (cpuinfo[2] & (1u << 27) && /* Save and Restore YMM regs */
cpuinfo[2] & (1u << 28) && /* AVX support is claimed */
_xgetbv(_XCR_XFEATURE_ENABLED_MASK)) { /* OS support */
simd |= SIMD_AVX;
printf(" AVX");
get_cpuid_ex(cpuinfo, 7, 0);
if (cpuinfo[1] & (1 << 5)) {
simd |= SIMD_AVX2;
printf(" AVX2");
}
}
if (simd == 0)
printf(" none\n");
else
printf("\n");
}
return simd;
}