Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : : Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk.com>
6 : :
7 : : PulseAudio is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU Lesser General Public License as published
9 : : by the Free Software Foundation; either version 2.1 of the License,
10 : : or (at your option) any later version.
11 : :
12 : : PulseAudio is distributed in the hope that it will be useful, but
13 : : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU Lesser General Public License
18 : : along with PulseAudio; if not, write to the Free Software
19 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 : : USA.
21 : : ***/
22 : :
23 : : #ifdef HAVE_CONFIG_H
24 : : #include <config.h>
25 : : #endif
26 : :
27 : : #include <pulse/sample.h>
28 : : #include <pulsecore/log.h>
29 : : #include <pulsecore/macro.h>
30 : :
31 : : #include "cpu-x86.h"
32 : : #include "remap.h"
33 : :
34 : : #define LOAD_SAMPLES \
35 : : " movq (%1), %%mm0 \n\t" \
36 : : " movq 8(%1), %%mm2 \n\t" \
37 : : " movq 16(%1), %%mm4 \n\t" \
38 : : " movq 24(%1), %%mm6 \n\t" \
39 : : " movq %%mm0, %%mm1 \n\t" \
40 : : " movq %%mm2, %%mm3 \n\t" \
41 : : " movq %%mm4, %%mm5 \n\t" \
42 : : " movq %%mm6, %%mm7 \n\t"
43 : :
44 : : #define UNPACK_SAMPLES(s) \
45 : : " punpckl"#s" %%mm0, %%mm0 \n\t" \
46 : : " punpckh"#s" %%mm1, %%mm1 \n\t" \
47 : : " punpckl"#s" %%mm2, %%mm2 \n\t" \
48 : : " punpckh"#s" %%mm3, %%mm3 \n\t" \
49 : : " punpckl"#s" %%mm4, %%mm4 \n\t" \
50 : : " punpckh"#s" %%mm5, %%mm5 \n\t" \
51 : : " punpckl"#s" %%mm6, %%mm6 \n\t" \
52 : : " punpckh"#s" %%mm7, %%mm7 \n\t"
53 : :
54 : : #define STORE_SAMPLES \
55 : : " movq %%mm0, (%0) \n\t" \
56 : : " movq %%mm1, 8(%0) \n\t" \
57 : : " movq %%mm2, 16(%0) \n\t" \
58 : : " movq %%mm3, 24(%0) \n\t" \
59 : : " movq %%mm4, 32(%0) \n\t" \
60 : : " movq %%mm5, 40(%0) \n\t" \
61 : : " movq %%mm6, 48(%0) \n\t" \
62 : : " movq %%mm7, 56(%0) \n\t" \
63 : : " add $32, %1 \n\t" \
64 : : " add $64, %0 \n\t"
65 : :
66 : : #define HANDLE_SINGLE_dq() \
67 : : " movd (%1), %%mm0 \n\t" \
68 : : " punpckldq %%mm0, %%mm0 \n\t" \
69 : : " movq %%mm0, (%0) \n\t" \
70 : : " add $4, %1 \n\t" \
71 : : " add $8, %0 \n\t"
72 : :
73 : : #define HANDLE_SINGLE_wd() \
74 : : " movw (%1), %w3 \n\t" \
75 : : " movd %3, %%mm0 \n\t" \
76 : : " punpcklwd %%mm0, %%mm0 \n\t" \
77 : : " movd %%mm0, (%0) \n\t" \
78 : : " add $2, %1 \n\t" \
79 : : " add $4, %0 \n\t"
80 : :
81 : : #define MONO_TO_STEREO(s,shift,mask) \
82 : : " mov %4, %2 \n\t" \
83 : : " sar $"#shift", %2 \n\t" \
84 : : " cmp $0, %2 \n\t" \
85 : : " je 2f \n\t" \
86 : : "1: \n\t" \
87 : : LOAD_SAMPLES \
88 : : UNPACK_SAMPLES(s) \
89 : : STORE_SAMPLES \
90 : : " dec %2 \n\t" \
91 : : " jne 1b \n\t" \
92 : : "2: \n\t" \
93 : : " mov %4, %2 \n\t" \
94 : : " and $"#mask", %2 \n\t" \
95 : : " je 4f \n\t" \
96 : : "3: \n\t" \
97 : : HANDLE_SINGLE_##s() \
98 : : " dec %2 \n\t" \
99 : : " jne 3b \n\t" \
100 : : "4: \n\t" \
101 : : " emms \n\t"
102 : :
103 : : #if defined (__i386__) || defined (__amd64__)
104 : 0 : static void remap_mono_to_stereo_mmx(pa_remap_t *m, void *dst, const void *src, unsigned n) {
105 : : pa_reg_x86 temp, temp2;
106 : :
107 [ # # # ]: 0 : switch (*m->format) {
108 : : case PA_SAMPLE_FLOAT32NE:
109 : : {
110 : 0 : __asm__ __volatile__ (
111 : : MONO_TO_STEREO(dq,3,7) /* do doubles to quads */
112 : : : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
113 : 0 : : "r" ((pa_reg_x86)n)
114 : : : "cc"
115 : : );
116 : 0 : break;
117 : : }
118 : : case PA_SAMPLE_S16NE:
119 : : {
120 : 0 : __asm__ __volatile__ (
121 : : MONO_TO_STEREO(wd,4,15) /* do words to doubles */
122 : : : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
123 : 0 : : "r" ((pa_reg_x86)n)
124 : : : "cc"
125 : : );
126 : 0 : break;
127 : : }
128 : : default:
129 : 0 : pa_assert_not_reached();
130 : : }
131 : 0 : }
132 : :
133 : : /* set the function that will execute the remapping based on the matrices */
134 : 0 : static void init_remap_mmx(pa_remap_t *m) {
135 : : unsigned n_oc, n_ic;
136 : :
137 : 0 : n_oc = m->o_ss->channels;
138 : 0 : n_ic = m->i_ss->channels;
139 : :
140 : : /* find some common channel remappings, fall back to full matrix operation. */
141 [ # # ][ # # ]: 0 : if (n_ic == 1 && n_oc == 2 &&
142 [ # # ]: 0 : m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
143 : 0 : m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_mmx;
144 : 0 : pa_log_info("Using MMX mono to stereo remapping");
145 : : }
146 : 0 : }
147 : : #endif /* defined (__i386__) || defined (__amd64__) */
148 : :
149 : 0 : void pa_remap_func_init_mmx(pa_cpu_x86_flag_t flags) {
150 : : #if defined (__i386__) || defined (__amd64__)
151 : :
152 [ # # ]: 0 : if (flags & PA_CPU_X86_MMX) {
153 : 0 : pa_log_info("Initialising MMX optimized remappers.");
154 : :
155 : 0 : pa_set_init_remap_func((pa_init_remap_func_t) init_remap_mmx);
156 : : }
157 : :
158 : : #endif /* defined (__i386__) || defined (__amd64__) */
159 : 0 : }
|