]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/vorbisdsp_init.c
Merge commit 'c6f1dc8e4cd967ae056698eafb891a08003c211c'
[ffmpeg] / libavcodec / x86 / vorbisdsp_init.c
1 /*
2  * Copyright (C) 2006 Loren Merritt <lorenm@u.washington.edu>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "config.h"
22 #include "libavutil/cpu.h"
23 #include "libavcodec/vorbisdsp.h"
24 #include "dsputil_mmx.h" // for ff_pdw_80000000
25
26 #if HAVE_INLINE_ASM
27 #if ARCH_X86_32
28 static void vorbis_inverse_coupling_3dnow(float *mag, float *ang, int blocksize)
29 {
30     int i;
31     __asm__ volatile ("pxor %%mm7, %%mm7":);
32     for (i = 0; i < blocksize; i += 2) {
33         __asm__ volatile (
34             "movq       %0, %%mm0   \n\t"
35             "movq       %1, %%mm1   \n\t"
36             "movq    %%mm0, %%mm2   \n\t"
37             "movq    %%mm1, %%mm3   \n\t"
38             "pfcmpge %%mm7, %%mm2   \n\t" // m <= 0.0
39             "pfcmpge %%mm7, %%mm3   \n\t" // a <= 0.0
40             "pslld     $31, %%mm2   \n\t" // keep only the sign bit
41             "pxor    %%mm2, %%mm1   \n\t"
42             "movq    %%mm3, %%mm4   \n\t"
43             "pand    %%mm1, %%mm3   \n\t"
44             "pandn   %%mm1, %%mm4   \n\t"
45             "pfadd   %%mm0, %%mm3   \n\t" // a = m + ((a < 0) & (a ^ sign(m)))
46             "pfsub   %%mm4, %%mm0   \n\t" // m = m + ((a > 0) & (a ^ sign(m)))
47             "movq    %%mm3, %1      \n\t"
48             "movq    %%mm0, %0      \n\t"
49             : "+m"(mag[i]), "+m"(ang[i])
50             :: "memory"
51         );
52     }
53     __asm__ volatile ("femms");
54 }
55 #endif
56
57 static void vorbis_inverse_coupling_sse(float *mag, float *ang, int blocksize)
58 {
59     int i;
60
61     __asm__ volatile (
62         "movaps  %0, %%xmm5 \n\t"
63         :: "m"(ff_pdw_80000000[0])
64     );
65     for (i = 0; i < blocksize; i += 4) {
66         __asm__ volatile (
67             "movaps      %0, %%xmm0 \n\t"
68             "movaps      %1, %%xmm1 \n\t"
69             "xorps   %%xmm2, %%xmm2 \n\t"
70             "xorps   %%xmm3, %%xmm3 \n\t"
71             "cmpleps %%xmm0, %%xmm2 \n\t" // m <= 0.0
72             "cmpleps %%xmm1, %%xmm3 \n\t" // a <= 0.0
73             "andps   %%xmm5, %%xmm2 \n\t" // keep only the sign bit
74             "xorps   %%xmm2, %%xmm1 \n\t"
75             "movaps  %%xmm3, %%xmm4 \n\t"
76             "andps   %%xmm1, %%xmm3 \n\t"
77             "andnps  %%xmm1, %%xmm4 \n\t"
78             "addps   %%xmm0, %%xmm3 \n\t" // a = m + ((a < 0) & (a ^ sign(m)))
79             "subps   %%xmm4, %%xmm0 \n\t" // m = m + ((a > 0) & (a ^ sign(m)))
80             "movaps  %%xmm3, %1     \n\t"
81             "movaps  %%xmm0, %0     \n\t"
82             : "+m"(mag[i]), "+m"(ang[i])
83             :: "memory"
84         );
85     }
86 }
87 #endif
88
89 void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp)
90 {
91 #if HAVE_INLINE_ASM
92     int mm_flags = av_get_cpu_flags();
93
94 #if ARCH_X86_32
95     if (mm_flags & AV_CPU_FLAG_3DNOW)
96         dsp->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow;
97 #endif /* ARCH_X86_32 */
98     if (mm_flags & AV_CPU_FLAG_SSE)
99         dsp->vorbis_inverse_coupling = vorbis_inverse_coupling_sse;
100 #endif /* HAVE_INLINE_ASM */
101 }