Split arch-dependent codes of dmix to separate files.
pcm_meter.c pcm_hooks.c pcm_lfloat.c pcm_ladspa.c \
pcm_direct.c pcm_dmix.c pcm_dsnoop.c pcm_dshare.c \
pcm_asym.c pcm_iec958.c pcm_softvol.c pcm_symbols.c
+
+EXTRA_SOURCES = pcm_dmix_i386.c pcm_dmix_x86_64.c pcm_dmix_generic.c
+
noinst_HEADERS = pcm_local.h pcm_plugin.h mask.h mask_inline.h \
interval.h interval_inline.h plugin_ops.h ladspa.h \
pcm_direct.h pcm_dmix_i386.h pcm_dmix_x86_64.h \
* FIXME: optimize it for different architectures
*/
-#ifdef __i386__
-
-#define ADD_AND_SATURATE
-
-#define MIX_AREAS1 mix_areas1
-#define MIX_AREAS1_MMX mix_areas1_mmx
-#define MIX_AREAS2 mix_areas2
-#define LOCK_PREFIX ""
-#include "pcm_dmix_i386.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS1_MMX
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-#define MIX_AREAS1 mix_areas1_smp
-#define MIX_AREAS1_MMX mix_areas1_smp_mmx
-#define MIX_AREAS2 mix_areas2_smp
-#define LOCK_PREFIX "lock ; "
-#include "pcm_dmix_i386.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS1_MMX
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
- FILE *in;
- char line[255];
- int smp = 0, mmx = 0;
-
- /* try to determine, if we have a MMX capable CPU */
- in = fopen("/proc/cpuinfo", "r");
- if (in) {
- while (!feof(in)) {
- fgets(line, sizeof(line), in);
- if (!strncmp(line, "processor", 9))
- smp++;
- else if (!strncmp(line, "flags", 5)) {
- if (strstr(line, " mmx"))
- mmx = 1;
- }
- }
- fclose(in);
- }
- // printf("MMX: %i, SMP: %i\n", mmx, smp);
- if (mmx) {
- dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp_mmx : mix_areas1_mmx;
- } else {
- dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
- }
- dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
-}
-#endif
-
-#ifdef __x86_64__
-#define ADD_AND_SATURATE
-
-#define MIX_AREAS1 mix_areas1
-#define MIX_AREAS2 mix_areas2
-#define LOCK_PREFIX ""
-#include "pcm_dmix_x86_64.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-#define MIX_AREAS1 mix_areas1_smp
-#define MIX_AREAS2 mix_areas2_smp
-#define LOCK_PREFIX "lock ; "
-#include "pcm_dmix_x86_64.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
- FILE *in;
- char line[255];
- int smp = 0;
-
- /* try to determine, if we have SMP */
- in = fopen("/proc/cpuinfo", "r");
- if (in) {
- while (!feof(in)) {
- fgets(line, sizeof(line), in);
- if (!strncmp(line, "processor", 9))
- smp++;
- }
- fclose(in);
- }
- // printf("SMP: %i\n", smp);
- dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
- dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
-}
-#endif
-
-
-#ifndef ADD_AND_SATURATE
-#warning Please, recode mix_areas1() routine to your architecture...
-static void mix_areas1(unsigned int size,
- volatile signed short *dst, signed short *src,
- volatile signed int *sum, size_t dst_step,
- size_t src_step, size_t sum_step)
-{
- register signed int sample, old_sample;
-
- for (;;) {
- sample = *src;
- old_sample = *sum;
- if (*dst == 0)
- sample -= old_sample;
- *sum += sample;
- do {
- old_sample = *sum;
- if (old_sample > 0x7fff)
- sample = 0x7fff;
- else if (old_sample < -0x8000)
- sample = -0x8000;
- else
- sample = old_sample;
- *dst = sample;
- } while (*sum != old_sample);
- if (!--size)
- return;
- ((char *)src) += src_step;
- ((char *)dst) += dst_step;
- ((char *)sum) += sum_step;
- }
-}
-
-#warning Please, recode mix_areas2() routine to your architecture...
-static void mix_areas2(unsigned int size,
- volatile signed int *dst, signed int *src,
- volatile signed int *sum, size_t dst_step,
- size_t src_step, size_t sum_step)
-{
- register signed int sample, old_sample;
-
- for (;;) {
- sample = *src / 256;
- old_sample = *sum;
- if (*dst == 0)
- sample -= old_sample;
- *sum += sample;
- do {
- old_sample = *sum;
- if (old_sample > 0x7fffff)
- sample = 0x7fffffff;
- else if (old_sample < -0x800000)
- sample = -0x80000000;
- else
- sample = old_sample * 256;
- *dst = sample;
- } while (*sum != old_sample);
- if (!--size)
- return;
- ((char *)src) += src_step;
- ((char *)dst) += dst_step;
- ((char *)sum) += sum_step;
- }
-}
-
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
- dmix->u.dmix.mix_areas1 = mix_areas1;
- dmix->u.dmix.mix_areas2 = mix_areas2;
-}
+#if defined(__i386__)
+#include "pcm_dmix_i386.c"
+#elif defined(__x86_64__)
+#include "pcm_dmix_x86_64.c"
+#else
+#include "pcm_dmix_generic.c"
#endif
static void mix_areas(snd_pcm_direct_t *dmix,
--- /dev/null
+#if defined(__i386__) || defined(__x86_64__)
+#define LOCK_PREFIX "lock ; "
+#define ARCH_ADD(p,a) \
+ __asm__ __volatile__(LOCK_PREFIX "addl %1,%0" \
+ :"=m" (*p) \
+ :"ir" (a), "m" (*p))
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long prev;
+ switch (size) {
+ case 1:
+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 2:
+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 4:
+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ }
+ return old;
+}
+
+#define ARCH_CMPXCHG(ptr,o,n)\
+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+ (unsigned long)(n),sizeof(*(ptr))))
+#endif
+
+#ifndef ARCH_ADD
+#warning Please, define atomic ADD and CMPXCHG for your architecture...
+#define ARCH_ADD(p,a) (*(p) += (a))
+#define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */
+#endif
+
+static void mix_areas1(unsigned int size,
+ volatile signed short *dst, signed short *src,
+ volatile signed int *sum, size_t dst_step,
+ size_t src_step, size_t sum_step)
+{
+ register signed int sample, old_sample;
+ src_step /= sizeof(*src);
+ dst_step /= sizeof(*dst);
+ sum_step /= sizeof(*sum);
+
+ for (;;) {
+ sample = *src;
+ old_sample = *sum;
+ if (ARCH_CMPXCHG(dst, 0, 1) == 0)
+ sample -= old_sample;
+ ARCH_ADD(sum, sample);
+ do {
+ old_sample = *sum;
+ if (old_sample > 0x7fff)
+ sample = 0x7fff;
+ else if (old_sample < -0x8000)
+ sample = -0x8000;
+ else
+ sample = old_sample;
+ *dst = sample;
+ } while (*sum != old_sample);
+ if (!--size)
+ return;
+ src += src_step;
+ dst += dst_step;
+ sum += sum_step;
+ }
+}
+
+static void mix_areas2(unsigned int size,
+ volatile signed int *dst, signed int *src,
+ volatile signed int *sum, size_t dst_step,
+ size_t src_step, size_t sum_step)
+{
+ register signed int sample, old_sample;
+ src_step /= sizeof(*src);
+ dst_step /= sizeof(*dst);
+ sum_step /= sizeof(*sum);
+
+ for (;;) {
+ sample = *src / 256;
+ old_sample = *sum;
+ if (ARCH_CMPXCHG(dst, 0, 1) == 0)
+ sample -= old_sample;
+ ARCH_ADD(sum, sample);
+ do {
+ old_sample = *sum;
+ if (old_sample > 0x7fffff)
+ sample = 0x7fffffff;
+ else if (old_sample < -0x800000)
+ sample = -0x80000000;
+ else
+ sample = old_sample * 256;
+ *dst = sample;
+ } while (*sum != old_sample);
+ if (!--size)
+ return;
+ src += src_step;
+ dst += dst_step;
+ sum += sum_step;
+ }
+}
+
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+ dmix->u.dmix.mix_areas1 = mix_areas1;
+ dmix->u.dmix.mix_areas2 = mix_areas2;
+}
--- /dev/null
+/*
+ * optimized mixing code for i386
+ */
+
+#define MIX_AREAS1 mix_areas1
+#define MIX_AREAS1_MMX mix_areas1_mmx
+#define MIX_AREAS2 mix_areas2
+#define LOCK_PREFIX ""
+#include "pcm_dmix_i386.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS1_MMX
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+#define MIX_AREAS1 mix_areas1_smp
+#define MIX_AREAS1_MMX mix_areas1_smp_mmx
+#define MIX_AREAS2 mix_areas2_smp
+#define LOCK_PREFIX "lock ; "
+#include "pcm_dmix_i386.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS1_MMX
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+ FILE *in;
+ char line[255];
+ int smp = 0, mmx = 0;
+
+ /* try to determine, if we have a MMX capable CPU */
+ in = fopen("/proc/cpuinfo", "r");
+ if (in) {
+ while (!feof(in)) {
+ fgets(line, sizeof(line), in);
+ if (!strncmp(line, "processor", 9))
+ smp++;
+ else if (!strncmp(line, "flags", 5)) {
+ if (strstr(line, " mmx"))
+ mmx = 1;
+ }
+ }
+ fclose(in);
+ }
+ // printf("MMX: %i, SMP: %i\n", mmx, smp);
+ if (mmx) {
+ dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp_mmx : mix_areas1_mmx;
+ } else {
+ dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
+ }
+ dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
+}
--- /dev/null
+/*
+ * optimized mixing code for x86-64
+ */
+
+#define MIX_AREAS1 mix_areas1
+#define MIX_AREAS2 mix_areas2
+#define LOCK_PREFIX ""
+#include "pcm_dmix_x86_64.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+#define MIX_AREAS1 mix_areas1_smp
+#define MIX_AREAS2 mix_areas2_smp
+#define LOCK_PREFIX "lock ; "
+#include "pcm_dmix_x86_64.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+ FILE *in;
+ char line[255];
+ int smp = 0;
+
+ /* try to determine, if we have SMP */
+ in = fopen("/proc/cpuinfo", "r");
+ if (in) {
+ while (!feof(in)) {
+ fgets(line, sizeof(line), in);
+ if (!strncmp(line, "processor", 9))
+ smp++;
+ }
+ fclose(in);
+ }
+ // printf("SMP: %i\n", smp);
+ dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
+ dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
+}