-static void
-pa_volume_s16re_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
-{
- pa_reg_x86 channel, temp;
-
- /* the max number of samples we process at a time, this is also the max amount
- * we overread the volume array, which should have enough padding. */
- channels = MAX (4, channels);
-
- __asm__ __volatile__ (
- " xor %3, %3 \n\t"
- " sar $1, %2 \n\t" /* length /= sizeof (int16_t) */
- " pcmpeqw %%mm6, %%mm6 \n\t" /* .. | ffff | ffff | */
- " pcmpeqw %%mm7, %%mm7 \n\t" /* .. | ffff | ffff | */
- " pslld $16, %%mm6 \n\t" /* .. | ffff | 0 | */
- " psrld $31, %%mm7 \n\t" /* .. | 0 | 1 | */
-
- " test $1, %2 \n\t" /* check for odd samples */
- " je 2f \n\t"
-
- " movd (%1, %3, 4), %%mm0 \n\t" /* | v0h | v0l | */
- " movw (%0), %4 \n\t" /* .. | p0 | */
- " rorw $8, %4 \n\t"
- " movd %4, %%mm1 \n\t"
- VOLUME_32x16 (%%mm1, %%mm0)
- " movd %%mm0, %4 \n\t" /* .. | p0*v0 | */
- " rorw $8, %4 \n\t"
- " movw %4, (%0) \n\t"
- " add $2, %0 \n\t"
- MOD_ADD ($1, %5)
-
- "2: \n\t"
- " sar $1, %2 \n\t" /* prepare for processing 2 samples at a time */
- " test $1, %2 \n\t" /* check for odd samples */
- " je 4f \n\t"
-
- "3: \n\t" /* do samples in groups of 2 */
- " movq (%1, %3, 4), %%mm0 \n\t" /* | v1h | v1l | v0h | v0l | */
- " movd (%0), %%mm1 \n\t" /* .. | p1 | p0 | */
- SWAP_16 (%%mm1)
- VOLUME_32x16 (%%mm1, %%mm0)
- SWAP_16 (%%mm0)
- " movd %%mm0, (%0) \n\t" /* .. | p1*v1 | p0*v0 | */
- " add $4, %0 \n\t"
- MOD_ADD ($2, %5)
-
- "4: \n\t"
- " sar $1, %2 \n\t" /* prepare for processing 4 samples at a time */
- " cmp $0, %2 \n\t"
- " je 6f \n\t"
-
- "5: \n\t" /* do samples in groups of 4 */
- " movq (%1, %3, 4), %%mm0 \n\t" /* | v1h | v1l | v0h | v0l | */
- " movq 8(%1, %3, 4), %%mm2 \n\t" /* | v3h | v3l | v2h | v2l | */
- " movd (%0), %%mm1 \n\t" /* .. | p1 | p0 | */
- " movd 4(%0), %%mm3 \n\t" /* .. | p3 | p2 | */
- SWAP_16_2 (%%mm1, %%mm3)
- VOLUME_32x16 (%%mm1, %%mm0)
- VOLUME_32x16 (%%mm3, %%mm2)
- SWAP_16_2 (%%mm0, %%mm2)
- " movd %%mm0, (%0) \n\t" /* .. | p1*v1 | p0*v0 | */
- " movd %%mm2, 4(%0) \n\t" /* .. | p3*v3 | p2*v2 | */
- " add $8, %0 \n\t"
- MOD_ADD ($4, %5)
- " dec %2 \n\t"
- " jne 5b \n\t"
-
- "6: \n\t"
- " emms \n\t"
-
- : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
- : "r" ((pa_reg_x86)channels)
- : "cc"
- );
+static void pa_volume_s16re_mmx(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
+ pa_reg_x86 channel, temp;
+
+ /* Channels must be at least 4, and always a multiple of the original number.
+ * This is also the max amount we overread the volume array, which should
+ * have enough padding. */
+ channels = channels == 3 ? 6 : PA_MAX (4U, channels);
+
+ __asm__ __volatile__ (
+ " xor %3, %3 \n\t"
+ " sar $1, %2 \n\t" /* length /= sizeof (int16_t) */
+ " pcmpeqw %%mm6, %%mm6 \n\t" /* .. | ffff | ffff | */
+ " pcmpeqw %%mm7, %%mm7 \n\t" /* .. | ffff | ffff | */
+ " pslld $16, %%mm6 \n\t" /* .. | ffff | 0 | */
+ " psrld $31, %%mm7 \n\t" /* .. | 0 | 1 | */
+
+ " test $1, %2 \n\t" /* check for odd samples */
+ " je 2f \n\t"
+
+ " movd (%1, %3, 4), %%mm0 \n\t" /* | v0h | v0l | */
+ " movw (%0), %w4 \n\t" /* .. | p0 | */
+ " rorw $8, %w4 \n\t"
+ " movd %4, %%mm1 \n\t"
+ VOLUME_32x16 (%%mm1, %%mm0)
+ " movd %%mm0, %4 \n\t" /* .. | p0*v0 | */
+ " rorw $8, %w4 \n\t"
+ " movw %w4, (%0) \n\t"
+ " add $2, %0 \n\t"
+ MOD_ADD ($1, %5)
+
+ "2: \n\t"
+ " sar $1, %2 \n\t" /* prepare for processing 2 samples at a time */
+ " test $1, %2 \n\t" /* check for odd samples */
+ " je 4f \n\t"
+
+ "3: \n\t" /* do samples in groups of 2 */
+ " movq (%1, %3, 4), %%mm0 \n\t" /* | v1h | v1l | v0h | v0l | */
+ " movd (%0), %%mm1 \n\t" /* .. | p1 | p0 | */
+ SWAP_16 (%%mm1)
+ VOLUME_32x16 (%%mm1, %%mm0)
+ SWAP_16 (%%mm0)
+ " movd %%mm0, (%0) \n\t" /* .. | p1*v1 | p0*v0 | */
+ " add $4, %0 \n\t"
+ MOD_ADD ($2, %5)
+
+ "4: \n\t"
+ " sar $1, %2 \n\t" /* prepare for processing 4 samples at a time */
+ " cmp $0, %2 \n\t"
+ " je 6f \n\t"
+
+ "5: \n\t" /* do samples in groups of 4 */
+ " movq (%1, %3, 4), %%mm0 \n\t" /* | v1h | v1l | v0h | v0l | */
+ " movq 8(%1, %3, 4), %%mm2 \n\t" /* | v3h | v3l | v2h | v2l | */
+ " movd (%0), %%mm1 \n\t" /* .. | p1 | p0 | */
+ " movd 4(%0), %%mm3 \n\t" /* .. | p3 | p2 | */
+ SWAP_16_2 (%%mm1, %%mm3)
+ VOLUME_32x16 (%%mm1, %%mm0)
+ VOLUME_32x16 (%%mm3, %%mm2)
+ SWAP_16_2 (%%mm0, %%mm2)
+ " movd %%mm0, (%0) \n\t" /* .. | p1*v1 | p0*v0 | */
+ " movd %%mm2, 4(%0) \n\t" /* .. | p3*v3 | p2*v2 | */
+ " add $8, %0 \n\t"
+ MOD_ADD ($4, %5)
+ " dec %2 \n\t"
+ " jne 5b \n\t"
+
+ "6: \n\t"
+ " emms \n\t"
+
+ : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
+ : "rm" ((pa_reg_x86)channels)
+ : "cc"
+ );