6545236d0038b2d6aed2264ede4b0ffd78f9e025
[ffmpeg.git] / libavcodec / x86 / pngdsp-init.c
1 /*
2  * x86 PNG optimizations.
3  * Copyright (c) 2008 Loren Merrit <lorenm@u.washington.edu>
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/cpu.h"
23 #include "libavutil/x86_cpu.h"
24 #include "libavcodec/pngdsp.h"
25 #include "dsputil_mmx.h"
26
27 #define PAETH(cpu, abs3)\
28 static void add_png_paeth_prediction_##cpu(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp)\
29 {\
30     x86_reg i = -bpp;\
31     x86_reg end = w-3;\
32     __asm__ volatile(\
33         "pxor      %%mm7, %%mm7 \n"\
34         "movd    (%1,%0), %%mm0 \n"\
35         "movd    (%2,%0), %%mm1 \n"\
36         "punpcklbw %%mm7, %%mm0 \n"\
37         "punpcklbw %%mm7, %%mm1 \n"\
38         "add       %4, %0 \n"\
39         "1: \n"\
40         "movq      %%mm1, %%mm2 \n"\
41         "movd    (%2,%0), %%mm1 \n"\
42         "movq      %%mm2, %%mm3 \n"\
43         "punpcklbw %%mm7, %%mm1 \n"\
44         "movq      %%mm2, %%mm4 \n"\
45         "psubw     %%mm1, %%mm3 \n"\
46         "psubw     %%mm0, %%mm4 \n"\
47         "movq      %%mm3, %%mm5 \n"\
48         "paddw     %%mm4, %%mm5 \n"\
49         abs3\
50         "movq      %%mm4, %%mm6 \n"\
51         "pminsw    %%mm5, %%mm6 \n"\
52         "pcmpgtw   %%mm6, %%mm3 \n"\
53         "pcmpgtw   %%mm5, %%mm4 \n"\
54         "movq      %%mm4, %%mm6 \n"\
55         "pand      %%mm3, %%mm4 \n"\
56         "pandn     %%mm3, %%mm6 \n"\
57         "pandn     %%mm0, %%mm3 \n"\
58         "movd    (%3,%0), %%mm0 \n"\
59         "pand      %%mm1, %%mm6 \n"\
60         "pand      %%mm4, %%mm2 \n"\
61         "punpcklbw %%mm7, %%mm0 \n"\
62         "movq      %6,    %%mm5 \n"\
63         "paddw     %%mm6, %%mm0 \n"\
64         "paddw     %%mm2, %%mm3 \n"\
65         "paddw     %%mm3, %%mm0 \n"\
66         "pand      %%mm5, %%mm0 \n"\
67         "movq      %%mm0, %%mm3 \n"\
68         "packuswb  %%mm3, %%mm3 \n"\
69         "movd      %%mm3, (%1,%0) \n"\
70         "add       %4, %0 \n"\
71         "cmp       %5, %0 \n"\
72         "jle 1b \n"\
73         :"+r"(i)\
74         :"r"(dst), "r"(top), "r"(src), "r"((x86_reg)bpp), "g"(end),\
75          "m"(ff_pw_255)\
76         :"memory"\
77     );\
78 }
79
80 #define ABS3_MMX2\
81         "psubw     %%mm5, %%mm7 \n"\
82         "pmaxsw    %%mm7, %%mm5 \n"\
83         "pxor      %%mm6, %%mm6 \n"\
84         "pxor      %%mm7, %%mm7 \n"\
85         "psubw     %%mm3, %%mm6 \n"\
86         "psubw     %%mm4, %%mm7 \n"\
87         "pmaxsw    %%mm6, %%mm3 \n"\
88         "pmaxsw    %%mm7, %%mm4 \n"\
89         "pxor      %%mm7, %%mm7 \n"
90
91 #define ABS3_SSSE3\
92         "pabsw     %%mm3, %%mm3 \n"\
93         "pabsw     %%mm4, %%mm4 \n"\
94         "pabsw     %%mm5, %%mm5 \n"
95
96 PAETH(mmx2, ABS3_MMX2)
97 #if HAVE_SSSE3
98 PAETH(ssse3, ABS3_SSSE3)
99 #endif
100
101 static void add_bytes_l2_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w)
102 {
103     x86_reg i=0;
104
105     __asm__ volatile(
106         "jmp 2f                         \n\t"
107         "1:                             \n\t"
108         "movq   (%2, %0), %%mm0         \n\t"
109         "movq  8(%2, %0), %%mm1         \n\t"
110         "paddb  (%3, %0), %%mm0         \n\t"
111         "paddb 8(%3, %0), %%mm1         \n\t"
112         "movq %%mm0,  (%1, %0)          \n\t"
113         "movq %%mm1, 8(%1, %0)          \n\t"
114         "add $16, %0                    \n\t"
115         "2:                             \n\t"
116         "cmp %4, %0                     \n\t"
117         " js 1b                         \n\t"
118         : "+r" (i)
119         : "r"(dst), "r"(src1), "r"(src2), "r"((x86_reg) w - 15)
120     );
121     for (; i < w; i++)
122         dst[i] = src1[i] + src2[i];
123 }
124
125 void ff_pngdsp_init_x86(PNGDSPContext *dsp)
126 {
127     int flags = av_get_cpu_flags();
128
129     if (flags & AV_CPU_FLAG_MMX)
130         dsp->add_bytes_l2         = add_bytes_l2_mmx;
131     if (flags & AV_CPU_FLAG_MMX2)
132         dsp->add_paeth_prediction = add_png_paeth_prediction_mmx2;
133     if (flags & AV_CPU_FLAG_SSSE3)
134         dsp->add_paeth_prediction = add_png_paeth_prediction_ssse3;
135 }