summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am1
-rw-r--r--src/pulsecore/cpu-x86.c122
-rw-r--r--src/pulsecore/cpu-x86.h61
3 files changed, 184 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b692e4a9..4e90d793 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -825,6 +825,7 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/resampler.c pulsecore/resampler.h \
pulsecore/rtpoll.c pulsecore/rtpoll.h \
pulsecore/sample-util.c pulsecore/sample-util.h \
+ pulsecore/cpu-x86.c \
pulsecore/svolume_c.c \
pulsecore/svolume_mmx.c pulsecore/svolume_sse.c \
pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \
diff --git a/src/pulsecore/cpu-x86.c b/src/pulsecore/cpu-x86.c
new file mode 100644
index 00000000..2da31c92
--- /dev/null
+++ b/src/pulsecore/cpu-x86.c
@@ -0,0 +1,122 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+ Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk>
+
+ PulseAudio 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.
+
+ PulseAudio 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 Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <pulsecore/log.h>
+
+#include "cpu-x86.h"
+
+#if defined (__i386__) || defined (__amd64__)
+static void
+get_cpuid (uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
+{
+ __asm__ __volatile__ (
+ " push %%"PA_REG_b" \n\t"
+ " cpuid \n\t"
+ " mov %%ebx, %%esi \n\t"
+ " pop %%"PA_REG_b" \n\t"
+
+ : "=a" (*a), "=S" (*b), "=c" (*c), "=d" (*d)
+ : "0" (op));
+}
+#endif
+
+static pa_cpu_x86_flag_t pa_cpu_x86_flags;
+
+void pa_cpu_init_x86 (void) {
+#if defined (__i386__) || defined (__amd64__)
+ uint32_t eax, ebx, ecx, edx;
+ uint32_t level;
+
+ /* get standard level */
+ get_cpuid (0x00000000, &level, &ebx, &ecx, &edx);
+ if (level >= 1) {
+ get_cpuid (0x00000001, &eax, &ebx, &ecx, &edx);
+
+ if (edx & (1<<23))
+ pa_cpu_x86_flags |= PA_CPU_X86_MMX;
+
+ if (edx & (1<<25))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSE;
+
+ if (edx & (1<<26))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSE2;
+
+ if (ecx & (1<<0))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSE3;
+
+ if (ecx & (1<<9))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSSE3;
+
+ if (ecx & (1<<19))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSE4_1;
+
+ if (ecx & (1<<20))
+ pa_cpu_x86_flags |= PA_CPU_X86_SSE4_2;
+ }
+
+ /* get extended level */
+ get_cpuid (0x80000000, &level, &ebx, &ecx, &edx);
+ if (level >= 0x80000001) {
+ get_cpuid (0x80000001, &eax, &ebx, &ecx, &edx);
+
+ if (edx & (1<<22))
+ pa_cpu_x86_flags |= PA_CPU_X86_MMXEXT;
+
+ if (edx & (1<<23))
+ pa_cpu_x86_flags |= PA_CPU_X86_MMX;
+
+ if (edx & (1<<30))
+ pa_cpu_x86_flags |= PA_CPU_X86_3DNOWEXT;
+
+ if (edx & (1<<31))
+ pa_cpu_x86_flags |= PA_CPU_X86_3DNOW;
+ }
+
+ pa_log_info ("CPU flags: %s%s%s%s%s%s%s%s%s%s",
+ (pa_cpu_x86_flags & PA_CPU_X86_MMX) ? "MMX " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSE) ? "SSE " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSE2) ? "SSE2 " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSE3) ? "SSE3 " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSSE3) ? "SSSE3 " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSE4_1) ? "SSE4_1 " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_SSE4_2) ? "SSE4_2 " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "",
+ (pa_cpu_x86_flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : "");
+
+ /* activate various optimisations */
+ if (pa_cpu_x86_flags & PA_CPU_X86_MMX) {
+ pa_volume_func_init_mmx (pa_cpu_x86_flags);
+ }
+ if (pa_cpu_x86_flags & PA_CPU_X86_SSE) {
+ pa_volume_func_init_sse (pa_cpu_x86_flags);
+ }
+#else
+ pa_cpu_x86_flags = 0;
+#endif
+}
diff --git a/src/pulsecore/cpu-x86.h b/src/pulsecore/cpu-x86.h
new file mode 100644
index 00000000..8158ea7a
--- /dev/null
+++ b/src/pulsecore/cpu-x86.h
@@ -0,0 +1,61 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+ Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk>
+
+ PulseAudio 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.
+
+ PulseAudio 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 Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <stdint.h>
+
+typedef enum pa_cpu_x86_flag {
+ PA_CPU_X86_MMX = (1 << 0),
+ PA_CPU_X86_MMXEXT = (1 << 1),
+ PA_CPU_X86_SSE = (1 << 2),
+ PA_CPU_X86_SSE2 = (1 << 3),
+ PA_CPU_X86_SSE3 = (1 << 4),
+ PA_CPU_X86_SSSE3 = (1 << 5),
+ PA_CPU_X86_SSE4_1 = (1 << 6),
+ PA_CPU_X86_SSE4_2 = (1 << 7),
+ PA_CPU_X86_3DNOW = (1 << 8),
+ PA_CPU_X86_3DNOWEXT = (1 << 9)
+} pa_cpu_x86_flag_t;
+
+void pa_cpu_init_x86 (void);
+
+
+#if defined (__i386__)
+typedef int32_t pa_reg_x86;
+#define PA_REG_a "eax"
+#define PA_REG_b "ebx"
+#define PA_REG_c "ecx"
+#define PA_REG_d "edx"
+#define PA_REG_D "edi"
+#define PA_REG_S "esi"
+#elif defined (__amd64__)
+typedef int64_t pa_reg_x86;
+#define PA_REG_a "rax"
+#define PA_REG_b "rbx"
+#define PA_REG_c "rcx"
+#define PA_REG_d "rdx"
+#define PA_REG_D "rdi"
+#define PA_REG_S "rsi"
+#endif
+
+/* some optimized functions */
+void pa_volume_func_init_mmx(pa_cpu_x86_flag_t flags);
+void pa_volume_func_init_sse(pa_cpu_x86_flag_t flags);