/** * @file cpu_feature.c * @brief CPU feature detection (CPU ID) * @author Patrick Roth - roth@stettbacher.ch * @copyright Stettbacher Signal Processing AG * * @remarks * *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* 
* */ #if __x86_64__ #include #include #include #include "cpu_feature.h" // level 1 static int cpu_feature_sse; static int cpu_feature_sse2; static int cpu_feature_sse3; static int cpu_feature_ssse3; static int cpu_feature_fma; static int cpu_feature_avx; // level 7 static int cpu_feature_avx2; /** * Check whether given CPU feature is available or not. * * @param type CPU feature type to check * @return not 0 if available, 0 if not */ int cpu_feature_support(enum cpu_feature_t type) { /* * Any CPU feature is disabled on 32 bit machine. */ switch(type) { case CPU_FEATURE_SSE: return cpu_feature_sse; case CPU_FEATURE_SSE2: return cpu_feature_sse2; case CPU_FEATURE_SSE3: return cpu_feature_sse3; case CPU_FEATURE_SSSE3: return cpu_feature_ssse3; case CPU_FEATURE_FMA: return cpu_feature_fma; case CPU_FEATURE_AVX: return cpu_feature_avx; case CPU_FEATURE_AVX2: return cpu_feature_avx2; } return 0; } /** * Initialize CPU features detection like MMX, SSE, SSE2, AVX etc. * This function read and handles the CPU IDs. * * @return 0 on success otherwise -1 */ int cpu_feature_init(void) { unsigned int cpuid_basic, /*cpuid_highest, */sig; unsigned int eax, ebx, ecx, edx; cpuid_basic = __get_cpuid_max(0, &sig); if(cpuid_basic == 0) { printf("%s: Basic CPUID is not supported\n", __func__); return -1; } // cpuid_highest = __get_cpuid_max(0x8000000, NULL); if(cpuid_basic >= 1) { __cpuid_count(1, 0, eax, ebx, ecx, edx); cpu_feature_sse = (edx & bit_SSE) != 0 ? 1:0; cpu_feature_sse2 = (edx & bit_SSE2) != 0 ? 1:0; cpu_feature_sse3 = (ecx & bit_SSE3) != 0 ? 1:0; cpu_feature_ssse3 = (ecx & bit_SSSE3) != 0 ? 1:0; cpu_feature_fma = (ecx & bit_FMA) != 0 ? 1:0; cpu_feature_avx = (ecx & bit_AVX) != 0 ? 1:0; } if(cpuid_basic >= 7) { __cpuid_count(7, 0, eax, ebx, ecx, edx); cpu_feature_avx2 = (ebx & bit_AVX2) != 0 ? 1:0; } // printf("%s: SSE %s\n", __func__, cpu_feature_sse != 0 ? "yes":"no"); // printf("%s: SSE2 %s\n", __func__, cpu_feature_sse2 != 0 ? "yes":"no"); // printf("%s: SSE3 %s\n", __func__, cpu_feature_sse3 != 0 ? "yes":"no"); // printf("%s: SSSE3 %s\n", __func__, cpu_feature_ssse3 != 0 ? "yes":"no"); // printf("%s: FMA %s\n", __func__, cpu_feature_fma != 0 ? "yes":"no"); // printf("%s: AVX %s\n", __func__, cpu_feature_avx != 0 ? "yes":"no"); // printf("%s: AVX2 %s\n", __func__, cpu_feature_avx2 != 0 ? "yes":"no"); return 0; } #endif // __x86_64__