#include <config.h>
#endif
-#include <string.h>
-
#include <pulse/sample.h>
+#include <pulse/volume.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
" punpckl"#s" %%mm4, %%mm4 \n\t" \
" punpckh"#s" %%mm5, %%mm5 \n\t" \
" punpckl"#s" %%mm6, %%mm6 \n\t" \
- " punpckh"#s" %%mm7, %%mm7 \n\t" \
+ " punpckh"#s" %%mm7, %%mm7 \n\t"
#define STORE_SAMPLES \
" movq %%mm0, (%0) \n\t" \
" add $32, %1 \n\t" \
" add $64, %0 \n\t"
-#define HANDLE_SINGLE(s) \
+#define HANDLE_SINGLE_dq() \
" movd (%1), %%mm0 \n\t" \
- " movq %%mm0, %%mm1 \n\t" \
- " punpckl"#s" %%mm0, %%mm0 \n\t" \
+ " punpckldq %%mm0, %%mm0 \n\t" \
" movq %%mm0, (%0) \n\t" \
" add $4, %1 \n\t" \
" add $8, %0 \n\t"
-#define MONO_TO_STEREO(s) \
- " mov %3, %2 \n\t" \
- " sar $3, %2 \n\t" \
- " cmp $0, %2 \n\t" \
- " je 2f \n\t" \
- "1: \n\t" \
- LOAD_SAMPLES \
- UNPACK_SAMPLES(s) \
- STORE_SAMPLES \
- " dec %2 \n\t" \
- " jne 1b \n\t" \
- "2: \n\t" \
- " mov %3, %2 \n\t" \
- " and $7, %2 \n\t" \
- " je 4f \n\t" \
- "3: \n\t" \
- HANDLE_SINGLE(s) \
- " dec %2 \n\t" \
- " jne 3b \n\t" \
- "4: \n\t" \
+#define HANDLE_SINGLE_wd() \
+ " movw (%1), %w3 \n\t" \
+ " movd %3, %%mm0 \n\t" \
+ " punpcklwd %%mm0, %%mm0 \n\t" \
+ " movd %%mm0, (%0) \n\t" \
+ " add $2, %1 \n\t" \
+ " add $4, %0 \n\t"
+
+#define MONO_TO_STEREO(s,shift,mask) \
+ " mov %4, %2 \n\t" \
+ " sar $"#shift", %2 \n\t" \
+ " cmp $0, %2 \n\t" \
+ " je 2f \n\t" \
+ "1: \n\t" \
+ LOAD_SAMPLES \
+ UNPACK_SAMPLES(s) \
+ STORE_SAMPLES \
+ " dec %2 \n\t" \
+ " jne 1b \n\t" \
+ "2: \n\t" \
+ " mov %4, %2 \n\t" \
+ " and $"#mask", %2 \n\t" \
+ " je 4f \n\t" \
+ "3: \n\t" \
+ HANDLE_SINGLE_##s() \
+ " dec %2 \n\t" \
+ " jne 3b \n\t" \
+ "4: \n\t" \
" emms \n\t"
-static void remap_mono_to_stereo_mmx (pa_remap_t *m, void *dst, const void *src, unsigned n) {
- pa_reg_x86 temp;
-
- switch (*m->format) {
- case PA_SAMPLE_FLOAT32NE:
- {
- __asm__ __volatile__ (
- MONO_TO_STEREO(dq) /* do doubles to quads */
- : "+r" (dst), "+r" (src), "=&r" (temp)
- : "r" ((pa_reg_x86)n)
- : "cc"
- );
- break;
- }
- case PA_SAMPLE_S16NE:
- {
- __asm__ __volatile__ (
- MONO_TO_STEREO(wd) /* do words to doubles */
- : "+r" (dst), "+r" (src), "=&r" (temp)
- : "r" ((pa_reg_x86)n)
- : "cc"
- );
- break;
- }
- default:
- pa_assert_not_reached();
- }
+#if defined (__i386__) || defined (__amd64__)
+static void remap_mono_to_stereo_s16ne_mmx(pa_remap_t *m, void *dst, const void *src, unsigned n) {
+ pa_reg_x86 temp, temp2;
+
+ __asm__ __volatile__ (
+ MONO_TO_STEREO(wd,4,15) /* do words to doubles */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
+ : "r" ((pa_reg_x86)n)
+ : "cc"
+ );
+}
+
+static void remap_mono_to_stereo_float32ne_mmx(pa_remap_t *m, void *dst, const void *src, unsigned n) {
+ pa_reg_x86 temp, temp2;
+
+ __asm__ __volatile__ (
+ MONO_TO_STEREO(dq,3,7) /* do doubles to quads */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
+ : "r" ((pa_reg_x86)n)
+ : "cc"
+ );
}
/* set the function that will execute the remapping based on the matrices */
-static void init_remap_mmx (pa_remap_t *m) {
+static void init_remap_mmx(pa_remap_t *m) {
unsigned n_oc, n_ic;
- n_oc = m->o_ss->channels;
- n_ic = m->i_ss->channels;
+ n_oc = m->o_ss.channels;
+ n_ic = m->i_ss.channels;
/* find some common channel remappings, fall back to full matrix operation. */
if (n_ic == 1 && n_oc == 2 &&
- m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
- m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_mmx;
+ m->map_table_i[0][0] == 0x10000 && m->map_table_i[1][0] == 0x10000) {
+
pa_log_info("Using MMX mono to stereo remapping");
+ pa_set_remap_func(m, remap_mono_to_stereo_s16ne_mmx, remap_mono_to_stereo_float32ne_mmx);
}
}
+#endif /* defined (__i386__) || defined (__amd64__) */
-void pa_remap_func_init_mmx (pa_cpu_x86_flag_t flags) {
+void pa_remap_func_init_mmx(pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising MMX optimized remappers.");
- pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
+ if (flags & PA_CPU_X86_MMX) {
+ pa_log_info("Initialising MMX optimized remappers.");
+
+ pa_set_init_remap_func((pa_init_remap_func_t) init_remap_mmx);
+ }
+
#endif /* defined (__i386__) || defined (__amd64__) */
}