]> code.delx.au - pulseaudio/commitdiff
cpu-x86: add cpu detection code and helpers
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 13 Aug 2009 15:11:43 +0000 (17:11 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 20 Aug 2009 09:31:02 +0000 (11:31 +0200)
Add CPU detection code and various macros and typdefs to make it easier to write
64 and 32 bit code.

src/Makefile.am
src/pulsecore/cpu-x86.c [new file with mode: 0644]
src/pulsecore/cpu-x86.h [new file with mode: 0644]

index b692e4a914c6e9fcfc76e1cb68c62f41cab96ef0..4e90d79391dc729c12e2ff3d6ff0b702f5417c92 100644 (file)
@@ -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 (file)
index 0000000..2da31c9
--- /dev/null
@@ -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 (file)
index 0000000..8158ea7
--- /dev/null
@@ -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);