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