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 : : " movdqu (%1), %%xmm0 \n\t" \
36 : : " movdqu 16(%1), %%xmm2 \n\t" \
37 : : " movdqu 32(%1), %%xmm4 \n\t" \
38 : : " movdqu 48(%1), %%xmm6 \n\t" \
39 : : " movdqa %%xmm0, %%xmm1 \n\t" \
40 : : " movdqa %%xmm2, %%xmm3 \n\t" \
41 : : " movdqa %%xmm4, %%xmm5 \n\t" \
42 : : " movdqa %%xmm6, %%xmm7 \n\t"
43 : :
44 : : #define UNPACK_SAMPLES(s) \
45 : : " punpckl"#s" %%xmm0, %%xmm0 \n\t" \
46 : : " punpckh"#s" %%xmm1, %%xmm1 \n\t" \
47 : : " punpckl"#s" %%xmm2, %%xmm2 \n\t" \
48 : : " punpckh"#s" %%xmm3, %%xmm3 \n\t" \
49 : : " punpckl"#s" %%xmm4, %%xmm4 \n\t" \
50 : : " punpckh"#s" %%xmm5, %%xmm5 \n\t" \
51 : : " punpckl"#s" %%xmm6, %%xmm6 \n\t" \
52 : : " punpckh"#s" %%xmm7, %%xmm7 \n\t"
53 : :
54 : : #define STORE_SAMPLES \
55 : : " movdqu %%xmm0, (%0) \n\t" \
56 : : " movdqu %%xmm1, 16(%0) \n\t" \
57 : : " movdqu %%xmm2, 32(%0) \n\t" \
58 : : " movdqu %%xmm3, 48(%0) \n\t" \
59 : : " movdqu %%xmm4, 64(%0) \n\t" \
60 : : " movdqu %%xmm5, 80(%0) \n\t" \
61 : : " movdqu %%xmm6, 96(%0) \n\t" \
62 : : " movdqu %%xmm7, 112(%0) \n\t" \
63 : : " add $64, %1 \n\t" \
64 : : " add $128, %0 \n\t"
65 : :
66 : : #define HANDLE_SINGLE_dq() \
67 : : " movd (%1), %%xmm0 \n\t" \
68 : : " punpckldq %%xmm0, %%xmm0 \n\t" \
69 : : " movq %%xmm0, (%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, %%xmm0 \n\t" \
76 : : " punpcklwd %%xmm0, %%xmm0 \n\t" \
77 : : " movd %%xmm0, (%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 : :
102 : : #if defined (__i386__) || defined (__amd64__)
103 : 0 : static void remap_mono_to_stereo_sse2(pa_remap_t *m, void *dst, const void *src, unsigned n) {
104 : : pa_reg_x86 temp, temp2;
105 : :
106 [ # # # ]: 0 : switch (*m->format) {
107 : : case PA_SAMPLE_FLOAT32NE:
108 : : {
109 : 0 : __asm__ __volatile__ (
110 : : MONO_TO_STEREO(dq, 4, 15) /* do doubles to quads */
111 : : : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
112 : 0 : : "r" ((pa_reg_x86)n)
113 : : : "cc"
114 : : );
115 : 0 : break;
116 : : }
117 : : case PA_SAMPLE_S16NE:
118 : : {
119 : 0 : __asm__ __volatile__ (
120 : : MONO_TO_STEREO(wd, 5, 31) /* do words to doubles */
121 : : : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
122 : 0 : : "r" ((pa_reg_x86)n)
123 : : : "cc"
124 : : );
125 : 0 : break;
126 : : }
127 : : default:
128 : 0 : pa_assert_not_reached();
129 : : }
130 : 0 : }
131 : :
132 : : /* set the function that will execute the remapping based on the matrices */
133 : 0 : static void init_remap_sse2(pa_remap_t *m) {
134 : : unsigned n_oc, n_ic;
135 : :
136 : 0 : n_oc = m->o_ss->channels;
137 : 0 : n_ic = m->i_ss->channels;
138 : :
139 : : /* find some common channel remappings, fall back to full matrix operation. */
140 [ # # ][ # # ]: 0 : if (n_ic == 1 && n_oc == 2 &&
141 [ # # ]: 0 : m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
142 : 0 : m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse2;
143 : 0 : pa_log_info("Using SSE mono to stereo remapping");
144 : : }
145 : 0 : }
146 : : #endif /* defined (__i386__) || defined (__amd64__) */
147 : :
148 : 0 : void pa_remap_func_init_sse(pa_cpu_x86_flag_t flags) {
149 : : #if defined (__i386__) || defined (__amd64__)
150 : :
151 [ # # ]: 0 : if (flags & PA_CPU_X86_SSE2) {
152 : 0 : pa_log_info("Initialising SSE2 optimized remappers.");
153 : 0 : pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse2);
154 : : }
155 : :
156 : : #endif /* defined (__i386__) || defined (__amd64__) */
157 : 0 : }
|