]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/vorbisdsp_init.c
1ba04b55b34ca492db5b2fb8a527c0f783b4637c
[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,
29                                           intptr_t blocksize)
30 {
31     int i;
32     __asm__ volatile ("pxor %%mm7, %%mm7":);
33     for (i = 0; i < blocksize; i += 2) {
34         __asm__ volatile (
35             "movq       %0, %%mm0   \n\t"
36             "movq       %1, %%mm1   \n\t"
37             "movq    %%mm0, %%mm2   \n\t"
38             "movq    %%mm1, %%mm3   \n\t"
39             "pfcmpge %%mm7, %%mm2   \n\t" // m <= 0.0
40             "pfcmpge %%mm7, %%mm3   \n\t" // a <= 0.0
41             "pslld     $31, %%mm2   \n\t" // keep only the sign bit
42             "pxor    %%mm2, %%mm1   \n\t"
43             "movq    %%mm3, %%mm4   \n\t"
44             "pand    %%mm1, %%mm3   \n\t"
45             "pandn   %%mm1, %%mm4   \n\t"
46             "pfadd   %%mm0, %%mm3   \n\t" // a = m + ((a < 0) & (a ^ sign(m)))
47             "pfsub   %%mm4, %%mm0   \n\t" // m = m + ((a > 0) & (a ^ sign(m)))
48             "movq    %%mm3, %1      \n\t"
49             "movq    %%mm0, %0      \n\t"
50             : "+m"(mag[i]), "+m"(ang[i])
51             :: "memory"
52         );
53     }
54     __asm__ volatile ("femms");
55 }
56 #endif
57
58 static void vorbis_inverse_coupling_sse(float *mag, float *ang,
59                                         intptr_t blocksize)
60 {
61     int i;
62
63     __asm__ volatile (
64         "movaps  %0, %%xmm5 \n\t"
65         :: "m"(ff_pdw_80000000[0])
66     );
67     for (i = 0; i < blocksize; i += 4) {
68         __asm__ volatile (
69             "movaps      %0, %%xmm0 \n\t"
70             "movaps      %1, %%xmm1 \n\t"
71             "xorps   %%xmm2, %%xmm2 \n\t"
72             "xorps   %%xmm3, %%xmm3 \n\t"
73             "cmpleps %%xmm0, %%xmm2 \n\t" // m <= 0.0
74             "cmpleps %%xmm1, %%xmm3 \n\t" // a <= 0.0
75             "andps   %%xmm5, %%xmm2 \n\t" // keep only the sign bit
76             "xorps   %%xmm2, %%xmm1 \n\t"
77             "movaps  %%xmm3, %%xmm4 \n\t"
78             "andps   %%xmm1, %%xmm3 \n\t"
79             "andnps  %%xmm1, %%xmm4 \n\t"
80             "addps   %%xmm0, %%xmm3 \n\t" // a = m + ((a < 0) & (a ^ sign(m)))
81             "subps   %%xmm4, %%xmm0 \n\t" // m = m + ((a > 0) & (a ^ sign(m)))
82             "movaps  %%xmm3, %1     \n\t"
83             "movaps  %%xmm0, %0     \n\t"
84             : "+m"(mag[i]), "+m"(ang[i])
85             :: "memory"
86         );
87     }
88 }
89 #endif
90
91 void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp)
92 {
93 #if HAVE_INLINE_ASM
94     int mm_flags = av_get_cpu_flags();
95
96 #if ARCH_X86_32
97     if (mm_flags & AV_CPU_FLAG_3DNOW)
98         dsp->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow;
99 #endif /* ARCH_X86_32 */
100     if (mm_flags & AV_CPU_FLAG_SSE)
101         dsp->vorbis_inverse_coupling = vorbis_inverse_coupling_sse;
102 #endif /* HAVE_INLINE_ASM */
103 }