]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/vc1dsp.asm
Merge commit '8bcadaacc2b8dc3c5d6569835a5ca20e62d3efca'
[ffmpeg] / libavcodec / x86 / vc1dsp.asm
1 ;******************************************************************************
2 ;* VC1 DSP optimizations
3 ;* Copyright (c) 2007 Christophe GISQUET <christophe.gisquet@free.fr>
4 ;* Copyright (c) 2009 David Conrad
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "libavutil/x86/x86util.asm"
24
25 cextern pw_4
26 cextern pw_5
27 cextern pw_9
28
29 section .text
30
31 ; dst_low, dst_high (src), zero
32 ; zero-extends one vector from 8 to 16 bits
33 %macro UNPACK_8TO16 4
34     mova      m%2, m%3
35     punpckh%1 m%3, m%4
36     punpckl%1 m%2, m%4
37 %endmacro
38
39 %macro STORE_4_WORDS 6
40 %if cpuflag(sse4)
41     pextrw %1, %5, %6+0
42     pextrw %2, %5, %6+1
43     pextrw %3, %5, %6+2
44     pextrw %4, %5, %6+3
45 %else
46     movd  %6d, %5
47 %if mmsize==16
48     psrldq %5, 4
49 %else
50     psrlq  %5, 32
51 %endif
52     mov    %1, %6w
53     shr    %6, 16
54     mov    %2, %6w
55     movd  %6d, %5
56     mov    %3, %6w
57     shr    %6, 16
58     mov    %4, %6w
59 %endif
60 %endmacro
61
62 ; in:  p1 p0 q0 q1, clobbers p0
63 ; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3
64 %macro VC1_LOOP_FILTER_A0 4
65     psubw  %1, %4
66     psubw  %2, %3
67     paddw  %1, %1
68     pmullw %2, [pw_5]
69     psubw  %1, %2
70     paddw  %1, [pw_4]
71     psraw  %1, 3
72 %endmacro
73
74 ; in: p0 q0 a0 a1 a2
75 ;     m0 m1 m7 m6 m5
76 ; %1: size
77 ; out: m0=p0' m1=q0'
78 %macro VC1_FILTER 1
79     PABSW   m4, m7
80     PABSW   m3, m6
81     PABSW   m2, m5
82     mova    m6, m4
83     pminsw  m3, m2
84     pcmpgtw m6, m3  ; if (a2 < a0 || a1 < a0)
85     psubw   m3, m4
86     pmullw  m3, [pw_5]   ; 5*(a3 - a0)
87     PABSW   m2, m3
88     psraw   m2, 3   ; abs(d/8)
89     pxor    m7, m3  ; d_sign ^= a0_sign
90
91     pxor    m5, m5
92     movd    m3, r2d
93 %if %1 > 4
94     punpcklbw m3, m3
95 %endif
96     punpcklbw m3, m5
97     pcmpgtw m3, m4  ; if (a0 < pq)
98     pand    m6, m3
99
100     mova    m3, m0
101     psubw   m3, m1
102     PABSW   m4, m3
103     psraw   m4, 1
104     pxor    m3, m7  ; d_sign ^ clip_sign
105     psraw   m3, 15
106     pminsw  m2, m4  ; min(d, clip)
107     pcmpgtw m4, m5
108     pand    m6, m4  ; filt3 (C return value)
109
110 ; each set of 4 pixels is not filtered if the 3rd is not
111 %if mmsize==16
112     pshuflw m4, m6, 0xaa
113 %if %1 > 4
114     pshufhw m4, m4, 0xaa
115 %endif
116 %else
117     pshufw  m4, m6, 0xaa
118 %endif
119     pandn   m3, m4
120     pand    m2, m6
121     pand    m3, m2  ; d final
122
123     psraw   m7, 15
124     pxor    m3, m7
125     psubw   m3, m7
126     psubw   m0, m3
127     paddw   m1, m3
128     packuswb m0, m0
129     packuswb m1, m1
130 %endmacro
131
132 ; 1st param: size of filter
133 ; 2nd param: mov suffix equivalent to the filter size
134 %macro VC1_V_LOOP_FILTER 2
135     pxor      m5, m5
136     mov%2     m6, [r4]
137     mov%2     m4, [r4+r1]
138     mov%2     m7, [r4+2*r1]
139     mov%2     m0, [r4+r3]
140     punpcklbw m6, m5
141     punpcklbw m4, m5
142     punpcklbw m7, m5
143     punpcklbw m0, m5
144
145     VC1_LOOP_FILTER_A0 m6, m4, m7, m0
146     mov%2     m1, [r0]
147     mov%2     m2, [r0+r1]
148     punpcklbw m1, m5
149     punpcklbw m2, m5
150     mova      m4, m0
151     VC1_LOOP_FILTER_A0 m7, m4, m1, m2
152     mov%2     m3, [r0+2*r1]
153     mov%2     m4, [r0+r3]
154     punpcklbw m3, m5
155     punpcklbw m4, m5
156     mova      m5, m1
157     VC1_LOOP_FILTER_A0 m5, m2, m3, m4
158
159     VC1_FILTER %1
160     mov%2 [r4+r3], m0
161     mov%2 [r0],    m1
162 %endmacro
163
164 ; 1st param: size of filter
165 ;     NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register
166 ; 2nd (optional) param: temp register to use for storing words
167 %macro VC1_H_LOOP_FILTER 1-2
168 %if %1 == 4
169     movq      m0, [r0     -4]
170     movq      m1, [r0+  r1-4]
171     movq      m2, [r0+2*r1-4]
172     movq      m3, [r0+  r3-4]
173     TRANSPOSE4x4B 0, 1, 2, 3, 4
174 %else
175     movq      m0, [r0     -4]
176     movq      m4, [r0+  r1-4]
177     movq      m1, [r0+2*r1-4]
178     movq      m5, [r0+  r3-4]
179     movq      m2, [r4     -4]
180     movq      m6, [r4+  r1-4]
181     movq      m3, [r4+2*r1-4]
182     movq      m7, [r4+  r3-4]
183     punpcklbw m0, m4
184     punpcklbw m1, m5
185     punpcklbw m2, m6
186     punpcklbw m3, m7
187     TRANSPOSE4x4W 0, 1, 2, 3, 4
188 %endif
189     pxor      m5, m5
190
191     UNPACK_8TO16 bw, 6, 0, 5
192     UNPACK_8TO16 bw, 7, 1, 5
193     VC1_LOOP_FILTER_A0 m6, m0, m7, m1
194     UNPACK_8TO16 bw, 4, 2, 5
195     mova    m0, m1                      ; m0 = p0
196     VC1_LOOP_FILTER_A0 m7, m1, m4, m2
197     UNPACK_8TO16 bw, 1, 3, 5
198     mova    m5, m4
199     VC1_LOOP_FILTER_A0 m5, m2, m1, m3
200     SWAP 1, 4                           ; m1 = q0
201
202     VC1_FILTER %1
203     punpcklbw m0, m1
204 %if %0 > 1
205     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2
206 %if %1 > 4
207     psrldq m0, 4
208     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2
209 %endif
210 %else
211     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0
212     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4
213 %endif
214 %endmacro
215
216
217 %macro START_V_FILTER 0
218     mov  r4, r0
219     lea  r3, [4*r1]
220     sub  r4, r3
221     lea  r3, [r1+2*r1]
222     imul r2, 0x01010101
223 %endmacro
224
225 %macro START_H_FILTER 1
226     lea  r3, [r1+2*r1]
227 %if %1 > 4
228     lea  r4, [r0+4*r1]
229 %endif
230     imul r2, 0x01010101
231 %endmacro
232
233 %macro VC1_LF 0
234 cglobal vc1_v_loop_filter_internal
235     VC1_V_LOOP_FILTER 4, d
236     ret
237
238 cglobal vc1_h_loop_filter_internal
239     VC1_H_LOOP_FILTER 4, r4
240     ret
241
242 ; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
243 cglobal vc1_v_loop_filter4, 3,5,0
244     START_V_FILTER
245     call vc1_v_loop_filter_internal
246     RET
247
248 ; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
249 cglobal vc1_h_loop_filter4, 3,5,0
250     START_H_FILTER 4
251     call vc1_h_loop_filter_internal
252     RET
253
254 ; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
255 cglobal vc1_v_loop_filter8, 3,5,0
256     START_V_FILTER
257     call vc1_v_loop_filter_internal
258     add  r4, 4
259     add  r0, 4
260     call vc1_v_loop_filter_internal
261     RET
262
263 ; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
264 cglobal vc1_h_loop_filter8, 3,5,0
265     START_H_FILTER 4
266     call vc1_h_loop_filter_internal
267     lea  r0, [r0+4*r1]
268     call vc1_h_loop_filter_internal
269     RET
270 %endmacro
271
272 INIT_MMX mmxext
273 VC1_LF
274
275 INIT_XMM sse2
276 ; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq)
277 cglobal vc1_v_loop_filter8, 3,5,8
278     START_V_FILTER
279     VC1_V_LOOP_FILTER 8, q
280     RET
281
282 ; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq)
283 cglobal vc1_h_loop_filter8, 3,6,8
284     START_H_FILTER 8
285     VC1_H_LOOP_FILTER 8, r5
286     RET
287
288 INIT_MMX ssse3
289 ; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
290 cglobal vc1_v_loop_filter4, 3,5,0
291     START_V_FILTER
292     VC1_V_LOOP_FILTER 4, d
293     RET
294
295 ; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
296 cglobal vc1_h_loop_filter4, 3,5,0
297     START_H_FILTER 4
298     VC1_H_LOOP_FILTER 4, r4
299     RET
300
301 INIT_XMM ssse3
302 ; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
303 cglobal vc1_v_loop_filter8, 3,5,8
304     START_V_FILTER
305     VC1_V_LOOP_FILTER 8, q
306     RET
307
308 ; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
309 cglobal vc1_h_loop_filter8, 3,6,8
310     START_H_FILTER 8
311     VC1_H_LOOP_FILTER 8, r5
312     RET
313
314 INIT_XMM sse4
315 ; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq)
316 cglobal vc1_h_loop_filter8, 3,5,8
317     START_H_FILTER 8
318     VC1_H_LOOP_FILTER 8
319     RET
320
321 %if HAVE_MMX_INLINE
322 ; Compute the rounder 32-r or 8-r and unpacks it to m7
323 %macro LOAD_ROUNDER_MMX 1 ; round
324     movd      m7, %1
325     punpcklwd m7, m7
326     punpckldq m7, m7
327 %endmacro
328
329 %macro SHIFT2_LINE 5 ; off, r0, r1, r2, r3
330     paddw          m%3, m%4
331     movh           m%2, [srcq + stride_neg2]
332     pmullw         m%3, m6
333     punpcklbw      m%2, m0
334     movh           m%5, [srcq + strideq]
335     psubw          m%3, m%2
336     punpcklbw      m%5, m0
337     paddw          m%3, m7
338     psubw          m%3, m%5
339     psraw          m%3, shift
340     movu   [dstq + %1], m%3
341     add           srcq, strideq
342 %endmacro
343
344 INIT_MMX mmx
345 ; void ff_vc1_put_ver_16b_shift2_mmx(int16_t *dst, const uint8_t *src,
346 ;                                    x86_reg stride, int rnd, int64_t shift)
347 ; Sacrificing m6 makes it possible to pipeline loads from src
348 %if ARCH_X86_32
349 cglobal vc1_put_ver_16b_shift2, 3,6,0, dst, src, stride
350     DECLARE_REG_TMP     3, 4, 5
351     %define rnd r3mp
352     %define shift qword r4m
353 %else ; X86_64
354 cglobal vc1_put_ver_16b_shift2, 4,7,0, dst, src, stride
355     DECLARE_REG_TMP     4, 5, 6
356     %define   rnd r3d
357     ; We need shift either in memory or in a mm reg as it's used in psraw
358     ; On WIN64, the arg is already on the stack
359     ; On UNIX64, m5 doesn't seem to be used
360 %if WIN64
361     %define shift r4mp
362 %else ; UNIX64
363     %define shift m5
364     mova shift, r4q
365 %endif ; WIN64
366 %endif ; X86_32
367 %define stride_neg2 t0q
368 %define stride_9minus4 t1q
369 %define i t2q
370     mov       stride_neg2, strideq
371     neg       stride_neg2
372     add       stride_neg2, stride_neg2
373     lea    stride_9minus4, [strideq * 9 - 4]
374     mov                 i, 3
375     LOAD_ROUNDER_MMX  rnd
376     mova               m6, [pw_9]
377     pxor               m0, m0
378 .loop:
379     movh               m2, [srcq]
380     add              srcq, strideq
381     movh               m3, [srcq]
382     punpcklbw          m2, m0
383     punpcklbw          m3, m0
384     SHIFT2_LINE         0, 1, 2, 3, 4
385     SHIFT2_LINE        24, 2, 3, 4, 1
386     SHIFT2_LINE        48, 3, 4, 1, 2
387     SHIFT2_LINE        72, 4, 1, 2, 3
388     SHIFT2_LINE        96, 1, 2, 3, 4
389     SHIFT2_LINE       120, 2, 3, 4, 1
390     SHIFT2_LINE       144, 3, 4, 1, 2
391     SHIFT2_LINE       168, 4, 1, 2, 3
392     sub              srcq, stride_9minus4
393     add              dstq, 8
394     dec                 i
395         jnz         .loop
396     REP_RET
397 %endif ; HAVE_MMX_INLINE