1 #if 0
2 //#if defined(__i386__) || defined(__x86_64__)
3 #define LOCK_PREFIX "lock ; "
4 #define ARCH_ADD(p,a) \
5 __asm__ __volatile__(LOCK_PREFIX "addl %1,%0" \
6 :"=m" (*p) \
7 :"ir" (a), "m" (*p))
8 struct __xchg_dummy { unsigned long a[100]; };
9 #define __xg(x) ((struct __xchg_dummy *)(x))
10 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
11 unsigned long new, int size)
12 {
13 unsigned long prev;
14 switch (size) {
15 case 1:
16 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
17 : "=a"(prev)
18 : "q"(new), "m"(*__xg(ptr)), "0"(old)
19 : "memory");
20 return prev;
21 case 2:
22 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
23 : "=a"(prev)
24 : "q"(new), "m"(*__xg(ptr)), "0"(old)
25 : "memory");
26 return prev;
27 case 4:
28 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
29 : "=a"(prev)
30 : "q"(new), "m"(*__xg(ptr)), "0"(old)
31 : "memory");
32 return prev;
33 }
34 return old;
35 }
36
37 #define ARCH_CMPXCHG(ptr,o,n)\
38 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
39 (unsigned long)(n),sizeof(*(ptr))))
40 #define IS_CONCURRENT 1 /* check race */
41 #endif
42
43 #ifndef ARCH_ADD
44 #define ARCH_ADD(p,a) (*(p) += (a))
45 #define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */
46 #define IS_CONCURRENT 0 /* no race check */
47 #endif
48
49 #if IS_CONCURRENT
mix_areas_16(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)50 static void mix_areas_16(unsigned int size,
51 volatile signed short *dst, signed short *src,
52 volatile signed int *sum, size_t dst_step,
53 size_t src_step, size_t sum_step)
54 {
55 register signed int sample, old_sample;
56
57 for (;;) {
58 sample = *src;
59 old_sample = *sum;
60 if (ARCH_CMPXCHG(dst, 0, 1) == 0)
61 sample -= old_sample;
62 ARCH_ADD(sum, sample);
63 do {
64 old_sample = *sum;
65 if (old_sample > 0x7fff)
66 sample = 0x7fff;
67 else if (old_sample < -0x8000)
68 sample = -0x8000;
69 else
70 sample = old_sample;
71 *dst = sample;
72 } while (IS_CONCURRENT && *sum != old_sample);
73 if (!--size)
74 return;
75 src = (signed short *) ((char *)src + src_step);
76 dst = (signed short *) ((char *)dst + dst_step);
77 sum = (signed int *) ((char *)sum + sum_step);
78 }
79 }
80
mix_areas_32(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)81 static void mix_areas_32(unsigned int size,
82 volatile signed int *dst, signed int *src,
83 volatile signed int *sum, size_t dst_step,
84 size_t src_step, size_t sum_step)
85 {
86 register signed int sample, old_sample;
87
88 for (;;) {
89 sample = *src >> 8;
90 old_sample = *sum;
91 if (ARCH_CMPXCHG(dst, 0, 1) == 0)
92 sample -= old_sample;
93 ARCH_ADD(sum, sample);
94 do {
95 old_sample = *sum;
96 if (old_sample > 0x7fffff)
97 sample = 0x7fffffff;
98 else if (old_sample < -0x800000)
99 sample = -0x80000000;
100 else
101 sample = old_sample * 256;
102 *dst = sample;
103 } while (IS_CONCURRENT && *sum != old_sample);
104 if (!--size)
105 return;
106 src = (signed int *) ((char *)src + src_step);
107 dst = (signed int *) ((char *)dst + dst_step);
108 sum = (signed int *) ((char *)sum + sum_step);
109 }
110 }
111
mix_select_callbacks(snd_pcm_direct_t *dmix)112 static void mix_select_callbacks(snd_pcm_direct_t *dmix)
113 {
114 dmix->u.dmix.mix_areas_16 = mix_areas_16;
115 dmix->u.dmix.mix_areas_32 = mix_areas_32;
116 }
117
118 #else
119
120 /* non-concurrent version, supporting both endians */
121 #define generic_dmix_supported_format \
122 ((1ULL << SND_PCM_FORMAT_S16_LE) | (1ULL << SND_PCM_FORMAT_S32_LE) |\
123 (1ULL << SND_PCM_FORMAT_S16_BE) | (1ULL << SND_PCM_FORMAT_S32_BE) |\
124 (1ULL << SND_PCM_FORMAT_S24_LE) | (1ULL << SND_PCM_FORMAT_S24_3LE) | \
125 (1ULL << SND_PCM_FORMAT_U8))
126
127 #include "bswap.h"
128
generic_mix_areas_16_native(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)129 static void generic_mix_areas_16_native(unsigned int size,
130 volatile signed short *dst,
131 signed short *src,
132 volatile signed int *sum,
133 size_t dst_step,
134 size_t src_step,
135 size_t sum_step)
136 {
137 register signed int sample;
138
139 for (;;) {
140 sample = *src;
141 if (! *dst) {
142 *sum = sample;
143 *dst = *src;
144 } else {
145 sample += *sum;
146 *sum = sample;
147 if (sample > 0x7fff)
148 sample = 0x7fff;
149 else if (sample < -0x8000)
150 sample = -0x8000;
151 *dst = sample;
152 }
153 if (!--size)
154 return;
155 src = (signed short *) ((char *)src + src_step);
156 dst = (signed short *) ((char *)dst + dst_step);
157 sum = (signed int *) ((char *)sum + sum_step);
158 }
159 }
160
generic_remix_areas_16_native(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)161 static void generic_remix_areas_16_native(unsigned int size,
162 volatile signed short *dst,
163 signed short *src,
164 volatile signed int *sum,
165 size_t dst_step,
166 size_t src_step,
167 size_t sum_step)
168 {
169 register signed int sample;
170
171 for (;;) {
172 sample = *src;
173 if (! *dst) {
174 *sum = -sample;
175 *dst = -sample;
176 } else {
177 *sum = sample = *sum - sample;
178 if (sample > 0x7fff)
179 sample = 0x7fff;
180 else if (sample < -0x8000)
181 sample = -0x8000;
182 *dst = sample;
183 }
184 if (!--size)
185 return;
186 src = (signed short *) ((char *)src + src_step);
187 dst = (signed short *) ((char *)dst + dst_step);
188 sum = (signed int *) ((char *)sum + sum_step);
189 }
190 }
191
generic_mix_areas_32_native(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)192 static void generic_mix_areas_32_native(unsigned int size,
193 volatile signed int *dst,
194 signed int *src,
195 volatile signed int *sum,
196 size_t dst_step,
197 size_t src_step,
198 size_t sum_step)
199 {
200 register signed int sample;
201
202 for (;;) {
203 sample = *src >> 8;
204 if (! *dst) {
205 *sum = sample;
206 *dst = *src;
207 } else {
208 sample += *sum;
209 *sum = sample;
210 if (sample > 0x7fffff)
211 sample = 0x7fffffff;
212 else if (sample < -0x800000)
213 sample = -0x80000000;
214 else
215 sample *= 256;
216 *dst = sample;
217 }
218 if (!--size)
219 return;
220 src = (signed int *) ((char *)src + src_step);
221 dst = (signed int *) ((char *)dst + dst_step);
222 sum = (signed int *) ((char *)sum + sum_step);
223 }
224 }
225
generic_remix_areas_32_native(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)226 static void generic_remix_areas_32_native(unsigned int size,
227 volatile signed int *dst,
228 signed int *src,
229 volatile signed int *sum,
230 size_t dst_step,
231 size_t src_step,
232 size_t sum_step)
233 {
234 register signed int sample;
235
236 for (;;) {
237 sample = *src >> 8;
238 if (! *dst) {
239 *sum = -sample;
240 *dst = -*src;
241 } else {
242 *sum = sample = *sum - sample;
243 if (sample > 0x7fffff)
244 sample = 0x7fffffff;
245 else if (sample < -0x800000)
246 sample = -0x80000000;
247 else
248 sample *= 256;
249 *dst = sample;
250 }
251 if (!--size)
252 return;
253 src = (signed int *) ((char *)src + src_step);
254 dst = (signed int *) ((char *)dst + dst_step);
255 sum = (signed int *) ((char *)sum + sum_step);
256 }
257 }
258
generic_mix_areas_16_swap(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)259 static void generic_mix_areas_16_swap(unsigned int size,
260 volatile signed short *dst,
261 signed short *src,
262 volatile signed int *sum,
263 size_t dst_step,
264 size_t src_step,
265 size_t sum_step)
266 {
267 register signed int sample;
268
269 for (;;) {
270 sample = (signed short) bswap_16(*src);
271 if (! *dst) {
272 *sum = sample;
273 *dst = *src;
274 } else {
275 sample += *sum;
276 *sum = sample;
277 if (sample > 0x7fff)
278 sample = 0x7fff;
279 else if (sample < -0x8000)
280 sample = -0x8000;
281 *dst = (signed short) bswap_16((signed short) sample);
282 }
283 if (!--size)
284 return;
285 src = (signed short *) ((char *)src + src_step);
286 dst = (signed short *) ((char *)dst + dst_step);
287 sum = (signed int *) ((char *)sum + sum_step);
288 }
289 }
290
generic_remix_areas_16_swap(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)291 static void generic_remix_areas_16_swap(unsigned int size,
292 volatile signed short *dst,
293 signed short *src,
294 volatile signed int *sum,
295 size_t dst_step,
296 size_t src_step,
297 size_t sum_step)
298 {
299 register signed int sample;
300
301 for (;;) {
302 sample = (signed short) bswap_16(*src);
303 if (! *dst) {
304 *sum = -sample;
305 *dst = (signed short) bswap_16((signed short) -sample);
306 } else {
307 *sum = sample = *sum - sample;
308 if (sample > 0x7fff)
309 sample = 0x7fff;
310 else if (sample < -0x8000)
311 sample = -0x8000;
312 *dst = (signed short) bswap_16((signed short) sample);
313 }
314 if (!--size)
315 return;
316 src = (signed short *) ((char *)src + src_step);
317 dst = (signed short *) ((char *)dst + dst_step);
318 sum = (signed int *) ((char *)sum + sum_step);
319 }
320 }
321
generic_mix_areas_32_swap(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)322 static void generic_mix_areas_32_swap(unsigned int size,
323 volatile signed int *dst,
324 signed int *src,
325 volatile signed int *sum,
326 size_t dst_step,
327 size_t src_step,
328 size_t sum_step)
329 {
330 register signed int sample;
331
332 for (;;) {
333 sample = (signed int) bswap_32(*src) >> 8;
334 if (! *dst) {
335 *sum = sample;
336 *dst = *src;
337 } else {
338 sample += *sum;
339 *sum = sample;
340 if (sample > 0x7fffff)
341 sample = 0x7fffffff;
342 else if (sample < -0x800000)
343 sample = -0x80000000;
344 else
345 sample *= 256;
346 *dst = bswap_32(sample);
347 }
348 if (!--size)
349 return;
350 src = (signed int *) ((char *)src + src_step);
351 dst = (signed int *) ((char *)dst + dst_step);
352 sum = (signed int *) ((char *)sum + sum_step);
353 }
354 }
355
generic_remix_areas_32_swap(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)356 static void generic_remix_areas_32_swap(unsigned int size,
357 volatile signed int *dst,
358 signed int *src,
359 volatile signed int *sum,
360 size_t dst_step,
361 size_t src_step,
362 size_t sum_step)
363 {
364 register signed int sample;
365
366 for (;;) {
367 sample = (signed int) bswap_32(*src) >> 8;
368 if (! *dst) {
369 *sum = -sample;
370 *dst = bswap_32(-sample);
371 } else {
372 *sum = sample = *sum - sample;
373 if (sample > 0x7fffff)
374 sample = 0x7fffffff;
375 else if (sample < -0x800000)
376 sample = -0x80000000;
377 else
378 sample *= 256;
379 *dst = bswap_32(sample);
380 }
381 if (!--size)
382 return;
383 src = (signed int *) ((char *)src + src_step);
384 dst = (signed int *) ((char *)dst + dst_step);
385 sum = (signed int *) ((char *)sum + sum_step);
386 }
387 }
388
389 /* always little endian */
generic_mix_areas_24(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)390 static void generic_mix_areas_24(unsigned int size,
391 volatile unsigned char *dst,
392 unsigned char *src,
393 volatile signed int *sum,
394 size_t dst_step,
395 size_t src_step,
396 size_t sum_step)
397 {
398 register signed int sample;
399
400 for (;;) {
401 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
402 if (!(dst[0] | dst[1] | dst[2])) {
403 *sum = sample;
404 } else {
405 sample += *sum;
406 *sum = sample;
407 if (sample > 0x7fffff)
408 sample = 0x7fffff;
409 else if (sample < -0x800000)
410 sample = -0x800000;
411 }
412 dst[0] = sample;
413 dst[1] = sample >> 8;
414 dst[2] = sample >> 16;
415 if (!--size)
416 return;
417 dst += dst_step;
418 src += src_step;
419 sum = (signed int *) ((char *)sum + sum_step);
420 }
421 }
422
generic_remix_areas_24(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)423 static void generic_remix_areas_24(unsigned int size,
424 volatile unsigned char *dst,
425 unsigned char *src,
426 volatile signed int *sum,
427 size_t dst_step,
428 size_t src_step,
429 size_t sum_step)
430 {
431 register signed int sample;
432
433 for (;;) {
434 sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
435 if (!(dst[0] | dst[1] | dst[2])) {
436 sample = -sample;
437 *sum = sample;
438 } else {
439 *sum = sample = *sum - sample;
440 if (sample > 0x7fffff)
441 sample = 0x7fffff;
442 else if (sample < -0x800000)
443 sample = -0x800000;
444 }
445 dst[0] = sample;
446 dst[1] = sample >> 8;
447 dst[2] = sample >> 16;
448 if (!--size)
449 return;
450 dst += dst_step;
451 src += src_step;
452 sum = (signed int *) ((char *)sum + sum_step);
453 }
454 }
455
generic_mix_areas_u8(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)456 static void generic_mix_areas_u8(unsigned int size,
457 volatile unsigned char *dst,
458 unsigned char *src,
459 volatile signed int *sum,
460 size_t dst_step,
461 size_t src_step,
462 size_t sum_step)
463 {
464 for (;;) {
465 register int sample = *src - 0x80;
466 if (*dst == 0x80) {
467 *sum = sample;
468 } else {
469 sample += *sum;
470 *sum = sample;
471 if (sample > 0x7f)
472 sample = 0x7f;
473 else if (sample < -0x80)
474 sample = -0x80;
475 }
476 *dst = sample + 0x80;
477 if (!--size)
478 return;
479 dst += dst_step;
480 src += src_step;
481 sum = (signed int *) ((char *)sum + sum_step);
482 }
483 }
484
generic_remix_areas_u8(unsigned int size, volatile unsigned char *dst, unsigned char *src, volatile signed int *sum, size_t dst_step, size_t src_step, size_t sum_step)485 static void generic_remix_areas_u8(unsigned int size,
486 volatile unsigned char *dst,
487 unsigned char *src,
488 volatile signed int *sum,
489 size_t dst_step,
490 size_t src_step,
491 size_t sum_step)
492 {
493 for (;;) {
494 register int sample = *src - 0x80;
495 if (*dst == 0x80) {
496 sample = -sample;
497 *sum = sample;
498 } else {
499 *sum = sample = *sum - sample;
500 if (sample > 0x7f)
501 sample = 0x7f;
502 else if (sample < -0x80)
503 sample = -0x80;
504 }
505 *dst = sample + 0x80;
506 if (!--size)
507 return;
508 dst += dst_step;
509 src += src_step;
510 sum = (signed int *) ((char *)sum + sum_step);
511 }
512 }
513
514
generic_mix_select_callbacks(snd_pcm_direct_t *dmix)515 static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
516 {
517 if (snd_pcm_format_cpu_endian(dmix->shmptr->s.format)) {
518 dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native;
519 dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native;
520 dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_native;
521 dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_native;
522 } else {
523 dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_swap;
524 dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap;
525 dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_swap;
526 dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_swap;
527 }
528 dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
529 dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
530 dmix->u.dmix.remix_areas_24 = generic_remix_areas_24;
531 dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8;
532 dmix->u.dmix.use_sem = 1;
533 }
534
535 #endif
536