eee42c27e6842f75daaf3c66c9be3943ae9db845
[ffmpeg.git] / 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 cextern pw_128
29
30 section .text
31
32 ; dst_low, dst_high (src), zero
33 ; zero-extends one vector from 8 to 16 bits
34 %macro UNPACK_8TO16 4
35     mova      m%2, m%3
36     punpckh%1 m%3, m%4
37     punpckl%1 m%2, m%4
38 %endmacro
39
40 %macro STORE_4_WORDS 6
41 %if cpuflag(sse4)
42     pextrw %1, %5, %6+0
43     pextrw %2, %5, %6+1
44     pextrw %3, %5, %6+2
45     pextrw %4, %5, %6+3
46 %else
47     movd  %6d, %5
48 %if mmsize==16
49     psrldq %5, 4
50 %else
51     psrlq  %5, 32
52 %endif
53     mov    %1, %6w
54     shr    %6, 16
55     mov    %2, %6w
56     movd  %6d, %5
57     mov    %3, %6w
58     shr    %6, 16
59     mov    %4, %6w
60 %endif
61 %endmacro
62
63 ; in:  p1 p0 q0 q1, clobbers p0
64 ; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3
65 %macro VC1_LOOP_FILTER_A0 4
66     psubw  %1, %4
67     psubw  %2, %3
68     paddw  %1, %1
69     pmullw %2, [pw_5]
70     psubw  %1, %2
71     paddw  %1, [pw_4]
72     psraw  %1, 3
73 %endmacro
74
75 ; in: p0 q0 a0 a1 a2
76 ;     m0 m1 m7 m6 m5
77 ; %1: size
78 ; out: m0=p0' m1=q0'
79 %macro VC1_FILTER 1
80     PABSW   m4, m7
81     PABSW   m3, m6
82     PABSW   m2, m5
83     mova    m6, m4
84     pminsw  m3, m2
85     pcmpgtw m6, m3  ; if (a2 < a0 || a1 < a0)
86     psubw   m3, m4
87     pmullw  m3, [pw_5]   ; 5*(a3 - a0)
88     PABSW   m2, m3
89     psraw   m2, 3   ; abs(d/8)
90     pxor    m7, m3  ; d_sign ^= a0_sign
91
92     pxor    m5, m5
93     movd    m3, r2d
94 %if %1 > 4
95     punpcklbw m3, m3
96 %endif
97     punpcklbw m3, m5
98     pcmpgtw m3, m4  ; if (a0 < pq)
99     pand    m6, m3
100
101     mova    m3, m0
102     psubw   m3, m1
103     PABSW   m4, m3
104     psraw   m4, 1
105     pxor    m3, m7  ; d_sign ^ clip_sign
106     psraw   m3, 15
107     pminsw  m2, m4  ; min(d, clip)
108     pcmpgtw m4, m5
109     pand    m6, m4  ; filt3 (C return value)
110
111 ; each set of 4 pixels is not filtered if the 3rd is not
112 %if mmsize==16
113     pshuflw m4, m6, 0xaa
114 %if %1 > 4
115     pshufhw m4, m4, 0xaa
116 %endif
117 %else
118     pshufw  m4, m6, 0xaa
119 %endif
120     pandn   m3, m4
121     pand    m2, m6
122     pand    m3, m2  ; d final
123
124     psraw   m7, 15
125     pxor    m3, m7
126     psubw   m3, m7
127     psubw   m0, m3
128     paddw   m1, m3
129     packuswb m0, m0
130     packuswb m1, m1
131 %endmacro
132
133 ; 1st param: size of filter
134 ; 2nd param: mov suffix equivalent to the filter size
135 %macro VC1_V_LOOP_FILTER 2
136     pxor      m5, m5
137     mov%2     m6, [r4]
138     mov%2     m4, [r4+r1]
139     mov%2     m7, [r4+2*r1]
140     mov%2     m0, [r4+r3]
141     punpcklbw m6, m5
142     punpcklbw m4, m5
143     punpcklbw m7, m5
144     punpcklbw m0, m5
145
146     VC1_LOOP_FILTER_A0 m6, m4, m7, m0
147     mov%2     m1, [r0]
148     mov%2     m2, [r0+r1]
149     punpcklbw m1, m5
150     punpcklbw m2, m5
151     mova      m4, m0
152     VC1_LOOP_FILTER_A0 m7, m4, m1, m2
153     mov%2     m3, [r0+2*r1]
154     mov%2     m4, [r0+r3]
155     punpcklbw m3, m5
156     punpcklbw m4, m5
157     mova      m5, m1
158     VC1_LOOP_FILTER_A0 m5, m2, m3, m4
159
160     VC1_FILTER %1
161     mov%2 [r4+r3], m0
162     mov%2 [r0],    m1
163 %endmacro
164
165 ; 1st param: size of filter
166 ;     NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register
167 ; 2nd (optional) param: temp register to use for storing words
168 %macro VC1_H_LOOP_FILTER 1-2
169 %if %1 == 4
170     movq      m0, [r0     -4]
171     movq      m1, [r0+  r1-4]
172     movq      m2, [r0+2*r1-4]
173     movq      m3, [r0+  r3-4]
174     TRANSPOSE4x4B 0, 1, 2, 3, 4
175 %else
176     movq      m0, [r0     -4]
177     movq      m4, [r0+  r1-4]
178     movq      m1, [r0+2*r1-4]
179     movq      m5, [r0+  r3-4]
180     movq      m2, [r4     -4]
181     movq      m6, [r4+  r1-4]
182     movq      m3, [r4+2*r1-4]
183     movq      m7, [r4+  r3-4]
184     punpcklbw m0, m4
185     punpcklbw m1, m5
186     punpcklbw m2, m6
187     punpcklbw m3, m7
188     TRANSPOSE4x4W 0, 1, 2, 3, 4
189 %endif
190     pxor      m5, m5
191
192     UNPACK_8TO16 bw, 6, 0, 5
193     UNPACK_8TO16 bw, 7, 1, 5
194     VC1_LOOP_FILTER_A0 m6, m0, m7, m1
195     UNPACK_8TO16 bw, 4, 2, 5
196     mova    m0, m1                      ; m0 = p0
197     VC1_LOOP_FILTER_A0 m7, m1, m4, m2
198     UNPACK_8TO16 bw, 1, 3, 5
199     mova    m5, m4
200     VC1_LOOP_FILTER_A0 m5, m2, m1, m3
201     SWAP 1, 4                           ; m1 = q0
202
203     VC1_FILTER %1
204     punpcklbw m0, m1
205 %if %0 > 1
206     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2
207 %if %1 > 4
208     psrldq m0, 4
209     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2
210 %endif
211 %else
212     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0
213     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4
214 %endif
215 %endmacro
216
217
218 %macro START_V_FILTER 0
219     mov  r4, r0
220     lea  r3, [4*r1]
221     sub  r4, r3
222     lea  r3, [r1+2*r1]
223     imul r2, 0x01010101
224 %endmacro
225
226 %macro START_H_FILTER 1
227     lea  r3, [r1+2*r1]
228 %if %1 > 4
229     lea  r4, [r0+4*r1]
230 %endif
231     imul r2, 0x01010101
232 %endmacro
233
234 %macro VC1_LF 0
235 cglobal vc1_v_loop_filter_internal
236     VC1_V_LOOP_FILTER 4, d
237     ret
238
239 cglobal vc1_h_loop_filter_internal
240     VC1_H_LOOP_FILTER 4, r4
241     ret
242
243 ; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
244 cglobal vc1_v_loop_filter4, 3,5,0
245     START_V_FILTER
246     call vc1_v_loop_filter_internal
247     RET
248
249 ; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
250 cglobal vc1_h_loop_filter4, 3,5,0
251     START_H_FILTER 4
252     call vc1_h_loop_filter_internal
253     RET
254
255 ; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
256 cglobal vc1_v_loop_filter8, 3,5,0
257     START_V_FILTER
258     call vc1_v_loop_filter_internal
259     add  r4, 4
260     add  r0, 4
261     call vc1_v_loop_filter_internal
262     RET
263
264 ; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
265 cglobal vc1_h_loop_filter8, 3,5,0
266     START_H_FILTER 4
267     call vc1_h_loop_filter_internal
268     lea  r0, [r0+4*r1]
269     call vc1_h_loop_filter_internal
270     RET
271 %endmacro
272
273 INIT_MMX mmxext
274 VC1_LF
275
276 INIT_XMM sse2
277 ; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq)
278 cglobal vc1_v_loop_filter8, 3,5,8
279     START_V_FILTER
280     VC1_V_LOOP_FILTER 8, q
281     RET
282
283 ; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq)
284 cglobal vc1_h_loop_filter8, 3,6,8
285     START_H_FILTER 8
286     VC1_H_LOOP_FILTER 8, r5
287     RET
288
289 INIT_MMX ssse3
290 ; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
291 cglobal vc1_v_loop_filter4, 3,5,0
292     START_V_FILTER
293     VC1_V_LOOP_FILTER 4, d
294     RET
295
296 ; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
297 cglobal vc1_h_loop_filter4, 3,5,0
298     START_H_FILTER 4
299     VC1_H_LOOP_FILTER 4, r4
300     RET
301
302 INIT_XMM ssse3
303 ; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
304 cglobal vc1_v_loop_filter8, 3,5,8
305     START_V_FILTER
306     VC1_V_LOOP_FILTER 8, q
307     RET
308
309 ; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
310 cglobal vc1_h_loop_filter8, 3,6,8
311     START_H_FILTER 8
312     VC1_H_LOOP_FILTER 8, r5
313     RET
314
315 INIT_XMM sse4
316 ; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq)
317 cglobal vc1_h_loop_filter8, 3,5,8
318     START_H_FILTER 8
319     VC1_H_LOOP_FILTER 8
320     RET
321
322 %if HAVE_MMX_INLINE
323
324 ; XXX some of these macros are not used right now, but they will in the future
325 ;     when more functions are ported.
326
327 %macro OP_PUT 2 ; dst, src
328 %endmacro
329
330 %macro OP_AVG 2 ; dst, src
331     pavgb           %1, %2
332 %endmacro
333
334 %macro NORMALIZE_MMX 1 ; shift
335     paddw           m3, m7 ; +bias-r
336     paddw           m4, m7 ; +bias-r
337     psraw           m3, %1
338     psraw           m4, %1
339 %endmacro
340
341 %macro TRANSFER_DO_PACK 2 ; op, dst
342     packuswb        m3, m4
343     %1              m3, [%2]
344     mova          [%2], m3
345 %endmacro
346
347 %macro TRANSFER_DONT_PACK 2 ; op, dst
348     %1              m3, [%2]
349     %1              m3, [%2 + mmsize]
350     mova          [%2], m3
351     mova [mmsize + %2], m4
352 %endmacro
353
354 ; see MSPEL_FILTER13_CORE for use as UNPACK macro
355 %macro DO_UNPACK 1 ; reg
356     punpcklbw       %1, m0
357 %endmacro
358 %macro DONT_UNPACK 1 ; reg
359 %endmacro
360
361 ; Compute the rounder 32-r or 8-r and unpacks it to m7
362 %macro LOAD_ROUNDER_MMX 1 ; round
363     movd      m7, %1
364     punpcklwd m7, m7
365     punpckldq m7, m7
366 %endmacro
367
368 %macro SHIFT2_LINE 5 ; off, r0, r1, r2, r3
369     paddw          m%3, m%4
370     movh           m%2, [srcq + stride_neg2]
371     pmullw         m%3, m6
372     punpcklbw      m%2, m0
373     movh           m%5, [srcq + strideq]
374     psubw          m%3, m%2
375     punpcklbw      m%5, m0
376     paddw          m%3, m7
377     psubw          m%3, m%5
378     psraw          m%3, shift
379     movu   [dstq + %1], m%3
380     add           srcq, strideq
381 %endmacro
382
383 INIT_MMX mmx
384 ; void ff_vc1_put_ver_16b_shift2_mmx(int16_t *dst, const uint8_t *src,
385 ;                                    x86_reg stride, int rnd, int64_t shift)
386 ; Sacrificing m6 makes it possible to pipeline loads from src
387 %if ARCH_X86_32
388 cglobal vc1_put_ver_16b_shift2, 3,6,0, dst, src, stride
389     DECLARE_REG_TMP     3, 4, 5
390     %define rnd r3mp
391     %define shift qword r4m
392 %else ; X86_64
393 cglobal vc1_put_ver_16b_shift2, 4,7,0, dst, src, stride
394     DECLARE_REG_TMP     4, 5, 6
395     %define   rnd r3d
396     ; We need shift either in memory or in a mm reg as it's used in psraw
397     ; On WIN64, the arg is already on the stack
398     ; On UNIX64, m5 doesn't seem to be used
399 %if WIN64
400     %define shift r4mp
401 %else ; UNIX64
402     %define shift m5
403     mova shift, r4q
404 %endif ; WIN64
405 %endif ; X86_32
406 %define stride_neg2 t0q
407 %define stride_9minus4 t1q
408 %define i t2q
409     mov       stride_neg2, strideq
410     neg       stride_neg2
411     add       stride_neg2, stride_neg2
412     lea    stride_9minus4, [strideq * 9 - 4]
413     mov                 i, 3
414     LOAD_ROUNDER_MMX  rnd
415     mova               m6, [pw_9]
416     pxor               m0, m0
417 .loop:
418     movh               m2, [srcq]
419     add              srcq, strideq
420     movh               m3, [srcq]
421     punpcklbw          m2, m0
422     punpcklbw          m3, m0
423     SHIFT2_LINE         0, 1, 2, 3, 4
424     SHIFT2_LINE        24, 2, 3, 4, 1
425     SHIFT2_LINE        48, 3, 4, 1, 2
426     SHIFT2_LINE        72, 4, 1, 2, 3
427     SHIFT2_LINE        96, 1, 2, 3, 4
428     SHIFT2_LINE       120, 2, 3, 4, 1
429     SHIFT2_LINE       144, 3, 4, 1, 2
430     SHIFT2_LINE       168, 4, 1, 2, 3
431     sub              srcq, stride_9minus4
432     add              dstq, 8
433     dec                 i
434         jnz         .loop
435     REP_RET
436 %undef rnd
437 %undef shift
438 %undef stride_neg2
439 %undef stride_9minus4
440 %undef i
441
442 ; void ff_vc1_*_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,
443 ;                                  const int16_t *src, int rnd);
444 ; Data is already unpacked, so some operations can directly be made from
445 ; memory.
446 %macro HOR_16B_SHIFT2 2 ; op, opname
447 cglobal vc1_%2_hor_16b_shift2, 4, 5, 0, dst, stride, src, rnd, h
448     mov                hq, 8
449     sub              srcq, 2
450     sub              rndd, (-1+9+9-1) * 1024 ; add -1024 bias
451     LOAD_ROUNDER_MMX rndq
452     mova               m5, [pw_9]
453     mova               m6, [pw_128]
454     pxor               m0, m0
455
456 .loop:
457     mova               m1, [srcq + 2 * 0]
458     mova               m2, [srcq + 2 * 0 + mmsize]
459     mova               m3, [srcq + 2 * 1]
460     mova               m4, [srcq + 2 * 1 + mmsize]
461     paddw              m3, [srcq + 2 * 2]
462     paddw              m4, [srcq + 2 * 2 + mmsize]
463     paddw              m1, [srcq + 2 * 3]
464     paddw              m2, [srcq + 2 * 3 + mmsize]
465     pmullw             m3, m5
466     pmullw             m4, m5
467     psubw              m3, m1
468     psubw              m4, m2
469     NORMALIZE_MMX      7
470     ; remove bias
471     paddw              m3, m6
472     paddw              m4, m6
473     TRANSFER_DO_PACK   %1, dstq
474     add              srcq, 24
475     add              dstq, strideq
476     dec                hq
477         jnz         .loop
478
479     RET
480 %endmacro
481
482 INIT_MMX mmx
483 HOR_16B_SHIFT2 OP_PUT, put
484
485 INIT_MMX mmxext
486 HOR_16B_SHIFT2 OP_AVG, avg
487 %endif ; HAVE_MMX_INLINE
488
489 %macro INV_TRANS_INIT 0
490     movsxdifnidn linesizeq, linesized
491     movd       m0, blockd
492     SPLATW     m0, m0
493     pxor       m1, m1
494     psubw      m1, m0
495     packuswb   m0, m0
496     packuswb   m1, m1
497
498     DEFINE_ARGS dest, linesize, linesize3
499     lea    linesize3q, [linesizeq*3]
500 %endmacro
501
502 %macro INV_TRANS_PROCESS 1
503     mov%1                  m2, [destq+linesizeq*0]
504     mov%1                  m3, [destq+linesizeq*1]
505     mov%1                  m4, [destq+linesizeq*2]
506     mov%1                  m5, [destq+linesize3q]
507     paddusb                m2, m0
508     paddusb                m3, m0
509     paddusb                m4, m0
510     paddusb                m5, m0
511     psubusb                m2, m1
512     psubusb                m3, m1
513     psubusb                m4, m1
514     psubusb                m5, m1
515     mov%1 [linesizeq*0+destq], m2
516     mov%1 [linesizeq*1+destq], m3
517     mov%1 [linesizeq*2+destq], m4
518     mov%1 [linesize3q +destq], m5
519 %endmacro
520
521 ; ff_vc1_inv_trans_?x?_dc_mmxext(uint8_t *dest, int linesize, int16_t *block)
522 INIT_MMX mmxext
523 cglobal vc1_inv_trans_4x4_dc, 3,4,0, dest, linesize, block
524     movsx         r3d, WORD [blockq]
525     mov        blockd, r3d             ; dc
526     shl        blockd, 4               ; 16 * dc
527     lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
528     sar        blockd, 3               ; >> 3
529     mov           r3d, blockd          ; dc
530     shl        blockd, 4               ; 16 * dc
531     lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
532     sar        blockd, 7               ; >> 7
533
534     INV_TRANS_INIT
535
536     INV_TRANS_PROCESS h
537     RET
538
539 INIT_MMX mmxext
540 cglobal vc1_inv_trans_4x8_dc, 3,4,0, dest, linesize, block
541     movsx         r3d, WORD [blockq]
542     mov        blockd, r3d             ; dc
543     shl        blockd, 4               ; 16 * dc
544     lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
545     sar        blockd, 3               ; >> 3
546     shl        blockd, 2               ;  4 * dc
547     lea        blockd, [blockq*3+64]   ; 12 * dc + 64
548     sar        blockd, 7               ; >> 7
549
550     INV_TRANS_INIT
551
552     INV_TRANS_PROCESS h
553     lea         destq, [destq+linesizeq*4]
554     INV_TRANS_PROCESS h
555     RET
556
557 INIT_MMX mmxext
558 cglobal vc1_inv_trans_8x4_dc, 3,4,0, dest, linesize, block
559     movsx      blockd, WORD [blockq]   ; dc
560     lea        blockd, [blockq*3+1]    ;  3 * dc + 1
561     sar        blockd, 1               ; >> 1
562     mov           r3d, blockd          ; dc
563     shl        blockd, 4               ; 16 * dc
564     lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
565     sar        blockd, 7               ; >> 7
566
567     INV_TRANS_INIT
568
569     INV_TRANS_PROCESS a
570     RET
571
572 INIT_MMX mmxext
573 cglobal vc1_inv_trans_8x8_dc, 3,3,0, dest, linesize, block
574     movsx      blockd, WORD [blockq]   ; dc
575     lea        blockd, [blockq*3+1]    ;  3 * dc + 1
576     sar        blockd, 1               ; >> 1
577     lea        blockd, [blockq*3+16]   ;  3 * dc + 16
578     sar        blockd, 5               ; >> 5
579
580     INV_TRANS_INIT
581
582     INV_TRANS_PROCESS a
583     lea         destq, [destq+linesizeq*4]
584     INV_TRANS_PROCESS a
585     RET