mpegvideo: Move OutFormat enum to mpegutils.h
[ffmpeg.git] / libavcodec / x86 / me_cmp.asm
1 ;*****************************************************************************
2 ;* SIMD-optimized motion compensation estimation
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 ;*
7 ;* This file is part of Libav.
8 ;*
9 ;* Libav is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
13 ;*
14 ;* Libav is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;* Lesser General Public License for more details.
18 ;*
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with Libav; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;*****************************************************************************
23
24 %include "libavutil/x86/x86util.asm"
25
26 SECTION .text
27
28 %macro DIFF_PIXELS_1 4
29     movh            %1, %3
30     movh            %2, %4
31     punpcklbw       %2, %1
32     punpcklbw       %1, %1
33     psubw           %1, %2
34 %endmacro
35
36 ; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3
37 ; %6=temporary storage location
38 ; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64)
39 %macro DIFF_PIXELS_8 6
40     DIFF_PIXELS_1   m0, m7, [%1     +%3], [%2     +%3]
41     DIFF_PIXELS_1   m1, m7, [%1+%4  +%3], [%2+%4  +%3]
42     DIFF_PIXELS_1   m2, m7, [%1+%4*2+%3], [%2+%4*2+%3]
43     add             %1, %5
44     add             %2, %5
45     DIFF_PIXELS_1   m3, m7, [%1     +%3], [%2     +%3]
46     DIFF_PIXELS_1   m4, m7, [%1+%4  +%3], [%2+%4  +%3]
47     DIFF_PIXELS_1   m5, m7, [%1+%4*2+%3], [%2+%4*2+%3]
48     DIFF_PIXELS_1   m6, m7, [%1+%5  +%3], [%2+%5  +%3]
49 %ifdef m8
50     DIFF_PIXELS_1   m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
51 %else
52     mova          [%6], m0
53     DIFF_PIXELS_1   m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
54     mova            m0, [%6]
55 %endif
56     sub             %1, %5
57     sub             %2, %5
58 %endmacro
59
60 %macro HADAMARD8 0
61     SUMSUB_BADC       w, 0, 1, 2, 3
62     SUMSUB_BADC       w, 4, 5, 6, 7
63     SUMSUB_BADC       w, 0, 2, 1, 3
64     SUMSUB_BADC       w, 4, 6, 5, 7
65     SUMSUB_BADC       w, 0, 4, 1, 5
66     SUMSUB_BADC       w, 2, 6, 3, 7
67 %endmacro
68
69 %macro ABS1_SUM 3
70     ABS1            %1, %2
71     paddusw         %3, %1
72 %endmacro
73
74 %macro ABS2_SUM 6
75     ABS2            %1, %2, %3, %4
76     paddusw         %5, %1
77     paddusw         %6, %2
78 %endmacro
79
80 %macro ABS_SUM_8x8_64 1
81     ABS2            m0, m1, m8, m9
82     ABS2_SUM        m2, m3, m8, m9, m0, m1
83     ABS2_SUM        m4, m5, m8, m9, m0, m1
84     ABS2_SUM        m6, m7, m8, m9, m0, m1
85     paddusw         m0, m1
86 %endmacro
87
88 %macro ABS_SUM_8x8_32 1
89     mova          [%1], m7
90     ABS1            m0, m7
91     ABS1            m1, m7
92     ABS1_SUM        m2, m7, m0
93     ABS1_SUM        m3, m7, m1
94     ABS1_SUM        m4, m7, m0
95     ABS1_SUM        m5, m7, m1
96     ABS1_SUM        m6, m7, m0
97     mova            m2, [%1]
98     ABS1_SUM        m2, m7, m1
99     paddusw         m0, m1
100 %endmacro
101
102 ; FIXME: HSUM saturates at 64k, while an 8x8 hadamard or dct block can get up to
103 ; about 100k on extreme inputs. But that's very unlikely to occur in natural video,
104 ; and it's even more unlikely to not have any alternative mvs/modes with lower cost.
105 %macro HSUM 3
106 %if cpuflag(sse2)
107     movhlps         %2, %1
108     paddusw         %1, %2
109     pshuflw         %2, %1, 0xE
110     paddusw         %1, %2
111     pshuflw         %2, %1, 0x1
112     paddusw         %1, %2
113     movd            %3, %1
114 %elif cpuflag(mmxext)
115     pshufw          %2, %1, 0xE
116     paddusw         %1, %2
117     pshufw          %2, %1, 0x1
118     paddusw         %1, %2
119     movd            %3, %1
120 %elif cpuflag(mmx)
121     mova            %2, %1
122     psrlq           %1, 32
123     paddusw         %1, %2
124     mova            %2, %1
125     psrlq           %1, 16
126     paddusw         %1, %2
127     movd            %3, %1
128 %endif
129 %endmacro
130
131 %macro STORE4 5
132     mova [%1+mmsize*0], %2
133     mova [%1+mmsize*1], %3
134     mova [%1+mmsize*2], %4
135     mova [%1+mmsize*3], %5
136 %endmacro
137
138 %macro LOAD4 5
139     mova            %2, [%1+mmsize*0]
140     mova            %3, [%1+mmsize*1]
141     mova            %4, [%1+mmsize*2]
142     mova            %5, [%1+mmsize*3]
143 %endmacro
144
145 %macro hadamard8_16_wrapper 2
146 cglobal hadamard8_diff, 4, 4, %1
147 %ifndef m8
148     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
149     SUB            rsp, pad
150 %endif
151     call hadamard8x8_diff %+ SUFFIX
152 %ifndef m8
153     ADD            rsp, pad
154 %endif
155     RET
156
157 cglobal hadamard8_diff16, 5, 6, %1
158 %ifndef m8
159     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
160     SUB            rsp, pad
161 %endif
162
163     call hadamard8x8_diff %+ SUFFIX
164     mov            r5d, eax
165
166     add             r1, 8
167     add             r2, 8
168     call hadamard8x8_diff %+ SUFFIX
169     add            r5d, eax
170
171     cmp            r4d, 16
172     jne .done
173
174     lea             r1, [r1+r3*8-8]
175     lea             r2, [r2+r3*8-8]
176     call hadamard8x8_diff %+ SUFFIX
177     add            r5d, eax
178
179     add             r1, 8
180     add             r2, 8
181     call hadamard8x8_diff %+ SUFFIX
182     add            r5d, eax
183
184 .done:
185     mov            eax, r5d
186 %ifndef m8
187     ADD            rsp, pad
188 %endif
189     RET
190 %endmacro
191
192 %macro HADAMARD8_DIFF 0-1
193 %if cpuflag(sse2)
194 hadamard8x8_diff %+ SUFFIX:
195     lea                          r0, [r3*3]
196     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize
197     HADAMARD8
198 %if ARCH_X86_64
199     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7,  8
200 %else
201     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7, [rsp+gprsize], [rsp+mmsize+gprsize]
202 %endif
203     HADAMARD8
204     ABS_SUM_8x8         rsp+gprsize
205     HSUM                        m0, m1, eax
206     and                         eax, 0xFFFF
207     ret
208
209 hadamard8_16_wrapper %1, 3
210 %elif cpuflag(mmx)
211 ALIGN 16
212 ; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,
213 ;                               uint8_t *src2, int stride, int h)
214 ; r0 = void *s = unused, int h = unused (always 8)
215 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
216 ; can simply call this 2x2x (and that's why we access rsp+gprsize
217 ; everywhere, which is rsp of calling func
218 hadamard8x8_diff %+ SUFFIX:
219     lea                          r0, [r3*3]
220
221     ; first 4x8 pixels
222     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize+0x60
223     HADAMARD8
224     mova         [rsp+gprsize+0x60], m7
225     TRANSPOSE4x4W                 0,  1,  2,  3,  7
226     STORE4              rsp+gprsize, m0, m1, m2, m3
227     mova                         m7, [rsp+gprsize+0x60]
228     TRANSPOSE4x4W                 4,  5,  6,  7,  0
229     STORE4         rsp+gprsize+0x40, m4, m5, m6, m7
230
231     ; second 4x8 pixels
232     DIFF_PIXELS_8                r1, r2,  4, r3, r0, rsp+gprsize+0x60
233     HADAMARD8
234     mova         [rsp+gprsize+0x60], m7
235     TRANSPOSE4x4W                 0,  1,  2,  3,  7
236     STORE4         rsp+gprsize+0x20, m0, m1, m2, m3
237     mova                         m7, [rsp+gprsize+0x60]
238     TRANSPOSE4x4W                 4,  5,  6,  7,  0
239
240     LOAD4          rsp+gprsize+0x40, m0, m1, m2, m3
241     HADAMARD8
242     ABS_SUM_8x8_32 rsp+gprsize+0x60
243     mova         [rsp+gprsize+0x60], m0
244
245     LOAD4          rsp+gprsize     , m0, m1, m2, m3
246     LOAD4          rsp+gprsize+0x20, m4, m5, m6, m7
247     HADAMARD8
248     ABS_SUM_8x8_32 rsp+gprsize
249     paddusw                      m0, [rsp+gprsize+0x60]
250
251     HSUM                         m0, m1, eax
252     and                         rax, 0xFFFF
253     ret
254
255 hadamard8_16_wrapper 0, 14
256 %endif
257 %endmacro
258
259 INIT_MMX mmx
260 HADAMARD8_DIFF
261
262 INIT_MMX mmxext
263 HADAMARD8_DIFF
264
265 INIT_XMM sse2
266 %if ARCH_X86_64
267 %define ABS_SUM_8x8 ABS_SUM_8x8_64
268 %else
269 %define ABS_SUM_8x8 ABS_SUM_8x8_32
270 %endif
271 HADAMARD8_DIFF 10
272
273 INIT_XMM ssse3
274 %define ABS_SUM_8x8 ABS_SUM_8x8_64
275 HADAMARD8_DIFF 9
276
277 INIT_XMM sse2
278 ; int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
279 ;                   int line_size, int h);
280 cglobal sse16, 5, 5, 8
281     shr      r4d, 1
282     pxor      m0, m0         ; mm0 = 0
283     pxor      m7, m7         ; mm7 holds the sum
284
285 .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned
286     movu      m1, [r1   ]    ; mm1 = pix1[0][0-15]
287     movu      m2, [r2   ]    ; mm2 = pix2[0][0-15]
288     movu      m3, [r1+r3]    ; mm3 = pix1[1][0-15]
289     movu      m4, [r2+r3]    ; mm4 = pix2[1][0-15]
290
291     ; todo: mm1-mm2, mm3-mm4
292     ; algo: subtract mm1 from mm2 with saturation and vice versa
293     ;       OR the result to get the absolute difference
294     mova      m5, m1
295     mova      m6, m3
296     psubusb   m1, m2
297     psubusb   m3, m4
298     psubusb   m2, m5
299     psubusb   m4, m6
300
301     por       m2, m1
302     por       m4, m3
303
304     ; now convert to 16-bit vectors so we can square them
305     mova      m1, m2
306     mova      m3, m4
307
308     punpckhbw m2, m0
309     punpckhbw m4, m0
310     punpcklbw m1, m0         ; mm1 not spread over (mm1,mm2)
311     punpcklbw m3, m0         ; mm4 not spread over (mm3,mm4)
312
313     pmaddwd   m2, m2
314     pmaddwd   m4, m4
315     pmaddwd   m1, m1
316     pmaddwd   m3, m3
317
318     lea       r1, [r1+r3*2]  ; pix1 += 2*line_size
319     lea       r2, [r2+r3*2]  ; pix2 += 2*line_size
320
321     paddd     m1, m2
322     paddd     m3, m4
323     paddd     m7, m1
324     paddd     m7, m3
325
326     dec       r4
327     jnz .next2lines
328
329     mova      m1, m7
330     psrldq    m7, 8          ; shift hi qword to lo
331     paddd     m7, m1
332     mova      m1, m7
333     psrldq    m7, 4          ; shift hi dword to lo
334     paddd     m7, m1
335     movd     eax, m7         ; return value
336     RET