153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdint.h> 2653a5a1b3Sopenharmony_ci 2753a5a1b3Sopenharmony_ci#ifdef HAVE_CPUID_H 2853a5a1b3Sopenharmony_ci#include <cpuid.h> 2953a5a1b3Sopenharmony_ci#endif 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#include <pulsecore/log.h> 3253a5a1b3Sopenharmony_ci 3353a5a1b3Sopenharmony_ci#include "cpu-x86.h" 3453a5a1b3Sopenharmony_ci 3553a5a1b3Sopenharmony_civoid pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) { 3653a5a1b3Sopenharmony_ci#if (defined(__i386__) || defined(__amd64__)) && defined(HAVE_CPUID_H) 3753a5a1b3Sopenharmony_ci uint32_t eax, ebx, ecx, edx; 3853a5a1b3Sopenharmony_ci uint32_t level; 3953a5a1b3Sopenharmony_ci 4053a5a1b3Sopenharmony_ci *flags = 0; 4153a5a1b3Sopenharmony_ci 4253a5a1b3Sopenharmony_ci /* get standard level */ 4353a5a1b3Sopenharmony_ci if (__get_cpuid(0x00000000, &level, &ebx, &ecx, &edx) == 0) 4453a5a1b3Sopenharmony_ci goto finish; 4553a5a1b3Sopenharmony_ci 4653a5a1b3Sopenharmony_ci if (level >= 1) { 4753a5a1b3Sopenharmony_ci if (__get_cpuid(0x00000001, &eax, &ebx, &ecx, &edx) == 0) 4853a5a1b3Sopenharmony_ci goto finish; 4953a5a1b3Sopenharmony_ci 5053a5a1b3Sopenharmony_ci if (edx & (1<<15)) 5153a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_CMOV; 5253a5a1b3Sopenharmony_ci 5353a5a1b3Sopenharmony_ci if (edx & (1<<23)) 5453a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_MMX; 5553a5a1b3Sopenharmony_ci 5653a5a1b3Sopenharmony_ci if (edx & (1<<25)) 5753a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSE; 5853a5a1b3Sopenharmony_ci 5953a5a1b3Sopenharmony_ci if (edx & (1<<26)) 6053a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSE2; 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ci if (ecx & (1<<0)) 6353a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSE3; 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_ci if (ecx & (1<<9)) 6653a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSSE3; 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_ci if (ecx & (1<<19)) 6953a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSE4_1; 7053a5a1b3Sopenharmony_ci 7153a5a1b3Sopenharmony_ci if (ecx & (1<<20)) 7253a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_SSE4_2; 7353a5a1b3Sopenharmony_ci } 7453a5a1b3Sopenharmony_ci 7553a5a1b3Sopenharmony_ci /* get extended level */ 7653a5a1b3Sopenharmony_ci if (__get_cpuid(0x80000000, &level, &ebx, &ecx, &edx) == 0) 7753a5a1b3Sopenharmony_ci goto finish; 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ci if (level >= 0x80000001) { 8053a5a1b3Sopenharmony_ci if (__get_cpuid(0x80000001, &eax, &ebx, &ecx, &edx) == 0) 8153a5a1b3Sopenharmony_ci goto finish; 8253a5a1b3Sopenharmony_ci 8353a5a1b3Sopenharmony_ci if (edx & (1<<22)) 8453a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_MMXEXT; 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_ci if (edx & (1<<23)) 8753a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_MMX; 8853a5a1b3Sopenharmony_ci 8953a5a1b3Sopenharmony_ci if (edx & (1<<30)) 9053a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_3DNOWEXT; 9153a5a1b3Sopenharmony_ci 9253a5a1b3Sopenharmony_ci if (edx & (1<<31)) 9353a5a1b3Sopenharmony_ci *flags |= PA_CPU_X86_3DNOW; 9453a5a1b3Sopenharmony_ci } 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_cifinish: 9753a5a1b3Sopenharmony_ci pa_log_info("CPU flags: %s%s%s%s%s%s%s%s%s%s%s", 9853a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_CMOV) ? "CMOV " : "", 9953a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_MMX) ? "MMX " : "", 10053a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSE) ? "SSE " : "", 10153a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSE2) ? "SSE2 " : "", 10253a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSE3) ? "SSE3 " : "", 10353a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSSE3) ? "SSSE3 " : "", 10453a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSE4_1) ? "SSE4_1 " : "", 10553a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_SSE4_2) ? "SSE4_2 " : "", 10653a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "", 10753a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "", 10853a5a1b3Sopenharmony_ci (*flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : ""); 10953a5a1b3Sopenharmony_ci#endif /* (defined(__i386__) || defined(__amd64__)) && defined(HAVE_CPUID_H) */ 11053a5a1b3Sopenharmony_ci} 11153a5a1b3Sopenharmony_ci 11253a5a1b3Sopenharmony_cibool pa_cpu_init_x86(pa_cpu_x86_flag_t *flags) { 11353a5a1b3Sopenharmony_ci#if defined (__i386__) || defined (__amd64__) 11453a5a1b3Sopenharmony_ci pa_cpu_get_x86_flags(flags); 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_ci /* activate various optimisations */ 11753a5a1b3Sopenharmony_ci#ifdef HAVE_MMX 11853a5a1b3Sopenharmony_ci if (*flags & PA_CPU_X86_MMX) { 11953a5a1b3Sopenharmony_ci pa_volume_func_init_mmx(*flags); 12053a5a1b3Sopenharmony_ci pa_remap_func_init_mmx(*flags); 12153a5a1b3Sopenharmony_ci } 12253a5a1b3Sopenharmony_ci#endif 12353a5a1b3Sopenharmony_ci 12453a5a1b3Sopenharmony_ci#ifdef HAVE_SSE 12553a5a1b3Sopenharmony_ci if (*flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) { 12653a5a1b3Sopenharmony_ci pa_volume_func_init_sse(*flags); 12753a5a1b3Sopenharmony_ci pa_remap_func_init_sse(*flags); 12853a5a1b3Sopenharmony_ci pa_convert_func_init_sse(*flags); 12953a5a1b3Sopenharmony_ci } 13053a5a1b3Sopenharmony_ci#endif 13153a5a1b3Sopenharmony_ci 13253a5a1b3Sopenharmony_ci return true; 13353a5a1b3Sopenharmony_ci#else /* defined (__i386__) || defined (__amd64__) */ 13453a5a1b3Sopenharmony_ci return false; 13553a5a1b3Sopenharmony_ci#endif /* defined (__i386__) || defined (__amd64__) */ 13653a5a1b3Sopenharmony_ci} 137