]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/h264_deblock.asm
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / x86 / h264_deblock.asm
1 ;*****************************************************************************
2 ;* MMX/SSE2/AVX-optimized H.264 deblocking code
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2011 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Jason Garrett-Glaser <darkshikari@gmail.com>
8 ;*          Oskar Arvidsson <oskar@irock.se>
9 ;*
10 ;* This file is part of FFmpeg.
11 ;*
12 ;* FFmpeg is free software; you can redistribute it and/or
13 ;* modify it under the terms of the GNU Lesser General Public
14 ;* License as published by the Free Software Foundation; either
15 ;* version 2.1 of the License, or (at your option) any later version.
16 ;*
17 ;* FFmpeg is distributed in the hope that it will be useful,
18 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;* Lesser General Public License for more details.
21 ;*
22 ;* You should have received a copy of the GNU Lesser General Public
23 ;* License along with FFmpeg; if not, write to the Free Software
24 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 ;******************************************************************************
26
27 %include "libavutil/x86/x86util.asm"
28
29 SECTION_RODATA
30
31 pb_A1: times 16 db 0xA1
32 pb_3_1: times 4 db 3, 1
33
34 SECTION .text
35
36 cextern pb_0
37 cextern pb_1
38 cextern pb_3
39
40 ; expands to [base],...,[base+7*stride]
41 %define PASS8ROWS(base, base3, stride, stride3) \
42     [base], [base+stride], [base+stride*2], [base3], \
43     [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4]
44
45 %define PASS8ROWS(base, base3, stride, stride3, offset) \
46     PASS8ROWS(base+offset, base3+offset, stride, stride3)
47
48 ; in: 8 rows of 4 bytes in %4..%11
49 ; out: 4 rows of 8 bytes in m0..m3
50 %macro TRANSPOSE4x8_LOAD 11
51     movh       m0, %4
52     movh       m2, %5
53     movh       m1, %6
54     movh       m3, %7
55     punpckl%1  m0, m2
56     punpckl%1  m1, m3
57     mova       m2, m0
58     punpckl%2  m0, m1
59     punpckh%2  m2, m1
60
61     movh       m4, %8
62     movh       m6, %9
63     movh       m5, %10
64     movh       m7, %11
65     punpckl%1  m4, m6
66     punpckl%1  m5, m7
67     mova       m6, m4
68     punpckl%2  m4, m5
69     punpckh%2  m6, m5
70
71     punpckh%3  m1, m0, m4
72     punpckh%3  m3, m2, m6
73     punpckl%3  m0, m4
74     punpckl%3  m2, m6
75 %endmacro
76
77 ; in: 4 rows of 8 bytes in m0..m3
78 ; out: 8 rows of 4 bytes in %1..%8
79 %macro TRANSPOSE8x4B_STORE 8
80     punpckhdq  m4, m0, m0
81     punpckhdq  m5, m1, m1
82     punpckhdq  m6, m2, m2
83
84     punpcklbw  m0, m1
85     punpcklbw  m2, m3
86     punpcklwd  m1, m0, m2
87     punpckhwd  m0, m2
88     movh       %1, m1
89     punpckhdq  m1, m1
90     movh       %2, m1
91     movh       %3, m0
92     punpckhdq  m0, m0
93     movh       %4, m0
94
95     punpckhdq  m3, m3
96     punpcklbw  m4, m5
97     punpcklbw  m6, m3
98     punpcklwd  m5, m4, m6
99     punpckhwd  m4, m6
100     movh       %5, m5
101     punpckhdq  m5, m5
102     movh       %6, m5
103     movh       %7, m4
104     punpckhdq  m4, m4
105     movh       %8, m4
106 %endmacro
107
108 %macro TRANSPOSE4x8B_LOAD 8
109     TRANSPOSE4x8_LOAD bw, wd, dq, %1, %2, %3, %4, %5, %6, %7, %8
110 %endmacro
111
112 %macro SBUTTERFLY3 4
113     punpckh%1  %4, %2, %3
114     punpckl%1  %2, %3
115 %endmacro
116
117 ; in: 8 rows of 8 (only the middle 6 pels are used) in %1..%8
118 ; out: 6 rows of 8 in [%9+0*16] .. [%9+5*16]
119 %macro TRANSPOSE6x8_MEM 9
120     RESET_MM_PERMUTATION
121     movq  m0, %1
122     movq  m1, %2
123     movq  m2, %3
124     movq  m3, %4
125     movq  m4, %5
126     movq  m5, %6
127     movq  m6, %7
128     SBUTTERFLY bw, 0, 1, 7
129     SBUTTERFLY bw, 2, 3, 7
130     SBUTTERFLY bw, 4, 5, 7
131     movq  [%9+0x10], m3
132     SBUTTERFLY3 bw, m6, %8, m7
133     SBUTTERFLY wd, 0, 2, 3
134     SBUTTERFLY wd, 4, 6, 3
135     punpckhdq m0, m4
136     movq  [%9+0x00], m0
137     SBUTTERFLY3 wd, m1, [%9+0x10], m3
138     SBUTTERFLY wd, 5, 7, 0
139     SBUTTERFLY dq, 1, 5, 0
140     SBUTTERFLY dq, 2, 6, 0
141     punpckldq m3, m7
142     movq  [%9+0x10], m2
143     movq  [%9+0x20], m6
144     movq  [%9+0x30], m1
145     movq  [%9+0x40], m5
146     movq  [%9+0x50], m3
147     RESET_MM_PERMUTATION
148 %endmacro
149
150 ; in: 8 rows of 8 in %1..%8
151 ; out: 8 rows of 8 in %9..%16
152 %macro TRANSPOSE8x8_MEM 16
153     RESET_MM_PERMUTATION
154     movq  m0, %1
155     movq  m1, %2
156     movq  m2, %3
157     movq  m3, %4
158     movq  m4, %5
159     movq  m5, %6
160     movq  m6, %7
161     SBUTTERFLY bw, 0, 1, 7
162     SBUTTERFLY bw, 2, 3, 7
163     SBUTTERFLY bw, 4, 5, 7
164     SBUTTERFLY3 bw, m6, %8, m7
165     movq  %9,  m5
166     SBUTTERFLY wd, 0, 2, 5
167     SBUTTERFLY wd, 4, 6, 5
168     SBUTTERFLY wd, 1, 3, 5
169     movq  %11, m6
170     movq  m6,  %9
171     SBUTTERFLY wd, 6, 7, 5
172     SBUTTERFLY dq, 0, 4, 5
173     SBUTTERFLY dq, 1, 6, 5
174     movq  %9,  m0
175     movq  %10, m4
176     movq  %13, m1
177     movq  %14, m6
178     SBUTTERFLY3 dq, m2, %11, m0
179     SBUTTERFLY dq, 3, 7, 4
180     movq  %11, m2
181     movq  %12, m0
182     movq  %15, m3
183     movq  %16, m7
184     RESET_MM_PERMUTATION
185 %endmacro
186
187 ; out: %4 = |%1-%2|>%3
188 ; clobbers: %5
189 %macro DIFF_GT 5
190 %if avx_enabled == 0
191     mova    %5, %2
192     mova    %4, %1
193     psubusb %5, %1
194     psubusb %4, %2
195 %else
196     psubusb %5, %2, %1
197     psubusb %4, %1, %2
198 %endif
199     por     %4, %5
200     psubusb %4, %3
201 %endmacro
202
203 ; out: %4 = |%1-%2|>%3
204 ; clobbers: %5
205 %macro DIFF_GT2 5
206 %if ARCH_X86_64
207     psubusb %5, %2, %1
208     psubusb %4, %1, %2
209 %else
210     mova    %5, %2
211     mova    %4, %1
212     psubusb %5, %1
213     psubusb %4, %2
214 %endif
215     psubusb %5, %3
216     psubusb %4, %3
217     pcmpeqb %4, %5
218 %endmacro
219
220 ; in: m0=p1 m1=p0 m2=q0 m3=q1 %1=alpha-1 %2=beta-1
221 ; out: m5=beta-1, m7=mask, %3=alpha-1
222 ; clobbers: m4,m6
223 %macro LOAD_MASK 2-3
224     movd     m4, %1
225     movd     m5, %2
226     SPLATW   m4, m4
227     SPLATW   m5, m5
228     packuswb m4, m4  ; 16x alpha-1
229     packuswb m5, m5  ; 16x beta-1
230 %if %0>2
231     mova     %3, m4
232 %endif
233     DIFF_GT  m1, m2, m4, m7, m6 ; |p0-q0| > alpha-1
234     DIFF_GT  m0, m1, m5, m4, m6 ; |p1-p0| > beta-1
235     por      m7, m4
236     DIFF_GT  m3, m2, m5, m4, m6 ; |q1-q0| > beta-1
237     por      m7, m4
238     pxor     m6, m6
239     pcmpeqb  m7, m6
240 %endmacro
241
242 ; in: m0=p1 m1=p0 m2=q0 m3=q1 m7=(tc&mask)
243 ; out: m1=p0' m2=q0'
244 ; clobbers: m0,3-6
245 %macro DEBLOCK_P0_Q0 0
246     pcmpeqb m4, m4
247     pxor    m5, m1, m2   ; p0^q0
248     pxor    m3, m4
249     pand    m5, [pb_1]   ; (p0^q0)&1
250     pavgb   m3, m0       ; (p1 - q1 + 256)>>1
251     pxor    m4, m1
252     pavgb   m3, [pb_3]   ; (((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2
253     pavgb   m4, m2       ; (q0 - p0 + 256)>>1
254     pavgb   m3, m5
255     mova    m6, [pb_A1]
256     paddusb m3, m4       ; d+128+33
257     psubusb m6, m3
258     psubusb m3, [pb_A1]
259     pminub  m6, m7
260     pminub  m3, m7
261     psubusb m1, m6
262     psubusb m2, m3
263     paddusb m1, m3
264     paddusb m2, m6
265 %endmacro
266
267 ; in: m1=p0 m2=q0
268 ;     %1=p1 %2=q2 %3=[q2] %4=[q1] %5=tc0 %6=tmp
269 ; out: [q1] = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 )
270 ; clobbers: q2, tmp, tc0
271 %macro LUMA_Q1 6
272     pavgb   %6, m1, m2
273     pavgb   %2, %6       ; avg(p2,avg(p0,q0))
274     pxor    %6, %3
275     pand    %6, [pb_1]   ; (p2^avg(p0,q0))&1
276     psubusb %2, %6       ; (p2+((p0+q0+1)>>1))>>1
277     psubusb %6, %1, %5
278     paddusb %5, %1
279     pmaxub  %2, %6
280     pminub  %2, %5
281     mova    %4, %2
282 %endmacro
283
284 %if ARCH_X86_64
285 ;-----------------------------------------------------------------------------
286 ; void deblock_v_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
287 ;-----------------------------------------------------------------------------
288 %macro DEBLOCK_LUMA 0
289 cglobal deblock_v_luma_8, 5,5,10
290     movd    m8, [r4] ; tc0
291     lea     r4, [r1*3]
292     dec     r2d        ; alpha-1
293     neg     r4
294     dec     r3d        ; beta-1
295     add     r4, r0     ; pix-3*stride
296
297     mova    m0, [r4+r1]   ; p1
298     mova    m1, [r4+2*r1] ; p0
299     mova    m2, [r0]      ; q0
300     mova    m3, [r0+r1]   ; q1
301     LOAD_MASK r2d, r3d
302
303     punpcklbw m8, m8
304     punpcklbw m8, m8 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
305     pcmpeqb m9, m9
306     pcmpeqb m9, m8
307     pandn   m9, m7
308     pand    m8, m9
309
310     movdqa  m3, [r4] ; p2
311     DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1
312     pand    m6, m9
313     psubb   m7, m8, m6
314     pand    m6, m8
315     LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4
316
317     movdqa  m4, [r0+2*r1] ; q2
318     DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1
319     pand    m6, m9
320     pand    m8, m6
321     psubb   m7, m6
322     mova    m3, [r0+r1]
323     LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m8, m6
324
325     DEBLOCK_P0_Q0
326     mova    [r4+2*r1], m1
327     mova    [r0], m2
328     RET
329
330 ;-----------------------------------------------------------------------------
331 ; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
332 ;-----------------------------------------------------------------------------
333 INIT_MMX cpuname
334 cglobal deblock_h_luma_8, 5,9
335     movsxd r7,  r1d
336     lea    r8,  [r7+r7*2]
337     lea    r6,  [r0-4]
338     lea    r5,  [r0-4+r8]
339 %if WIN64
340     sub    rsp, 0x98
341     %define pix_tmp rsp+0x30
342 %else
343     sub    rsp, 0x68
344     %define pix_tmp rsp
345 %endif
346
347     ; transpose 6x16 -> tmp space
348     TRANSPOSE6x8_MEM  PASS8ROWS(r6, r5, r7, r8), pix_tmp
349     lea    r6, [r6+r7*8]
350     lea    r5, [r5+r7*8]
351     TRANSPOSE6x8_MEM  PASS8ROWS(r6, r5, r7, r8), pix_tmp+8
352
353     ; vertical filter
354     ; alpha, beta, tc0 are still in r2d, r3d, r4
355     ; don't backup r6, r5, r7, r8 because deblock_v_luma_sse2 doesn't use them
356     lea    r0, [pix_tmp+0x30]
357     mov    r1d, 0x10
358 %if WIN64
359     mov    [rsp+0x20], r4
360 %endif
361     call   deblock_v_luma_8
362
363     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)
364     add    r6, 2
365     add    r5, 2
366     movq   m0, [pix_tmp+0x18]
367     movq   m1, [pix_tmp+0x28]
368     movq   m2, [pix_tmp+0x38]
369     movq   m3, [pix_tmp+0x48]
370     TRANSPOSE8x4B_STORE  PASS8ROWS(r6, r5, r7, r8)
371
372     shl    r7,  3
373     sub    r6,  r7
374     sub    r5,  r7
375     shr    r7,  3
376     movq   m0, [pix_tmp+0x10]
377     movq   m1, [pix_tmp+0x20]
378     movq   m2, [pix_tmp+0x30]
379     movq   m3, [pix_tmp+0x40]
380     TRANSPOSE8x4B_STORE  PASS8ROWS(r6, r5, r7, r8)
381
382 %if WIN64
383     add    rsp, 0x98
384 %else
385     add    rsp, 0x68
386 %endif
387     RET
388 %endmacro
389
390 INIT_XMM sse2
391 DEBLOCK_LUMA
392 %if HAVE_AVX_EXTERNAL
393 INIT_XMM avx
394 DEBLOCK_LUMA
395 %endif
396
397 %else
398
399 %macro DEBLOCK_LUMA 2
400 ;-----------------------------------------------------------------------------
401 ; void deblock_v8_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
402 ;-----------------------------------------------------------------------------
403 cglobal deblock_%1_luma_8, 5,5,8,2*%2
404     lea     r4, [r1*3]
405     dec     r2     ; alpha-1
406     neg     r4
407     dec     r3     ; beta-1
408     add     r4, r0 ; pix-3*stride
409
410     mova    m0, [r4+r1]   ; p1
411     mova    m1, [r4+2*r1] ; p0
412     mova    m2, [r0]      ; q0
413     mova    m3, [r0+r1]   ; q1
414     LOAD_MASK r2, r3
415
416     mov     r3, r4mp
417     pcmpeqb m3, m3
418     movd    m4, [r3] ; tc0
419     punpcklbw m4, m4
420     punpcklbw m4, m4 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
421     mova   [esp+%2], m4 ; tc
422     pcmpgtb m4, m3
423     mova    m3, [r4] ; p2
424     pand    m4, m7
425     mova   [esp], m4 ; mask
426
427     DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1
428     pand    m6, m4
429     pand    m4, [esp+%2] ; tc
430     psubb   m7, m4, m6
431     pand    m6, m4
432     LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4
433
434     mova    m4, [r0+2*r1] ; q2
435     DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1
436     pand    m6, [esp] ; mask
437     mova    m5, [esp+%2] ; tc
438     psubb   m7, m6
439     pand    m5, m6
440     mova    m3, [r0+r1]
441     LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m5, m6
442
443     DEBLOCK_P0_Q0
444     mova    [r4+2*r1], m1
445     mova    [r0], m2
446     RET
447
448 ;-----------------------------------------------------------------------------
449 ; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
450 ;-----------------------------------------------------------------------------
451 INIT_MMX cpuname
452 cglobal deblock_h_luma_8, 0,5,8,0x60+HAVE_ALIGNED_STACK*12
453     mov    r0, r0mp
454     mov    r3, r1m
455     lea    r4, [r3*3]
456     sub    r0, 4
457     lea    r1, [r0+r4]
458 %define pix_tmp esp+12*HAVE_ALIGNED_STACK
459
460     ; transpose 6x16 -> tmp space
461     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp
462     lea    r0, [r0+r3*8]
463     lea    r1, [r1+r3*8]
464     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp+8
465
466     ; vertical filter
467     lea    r0, [pix_tmp+0x30]
468     PUSH   dword r4m
469     PUSH   dword r3m
470     PUSH   dword r2m
471     PUSH   dword 16
472     PUSH   dword r0
473     call   deblock_%1_luma_8
474 %ifidn %1, v8
475     add    dword [esp   ], 8 ; pix_tmp+0x38
476     add    dword [esp+16], 2 ; tc0+2
477     call   deblock_%1_luma_8
478 %endif
479     ADD    esp, 20
480
481     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)
482     mov    r0, r0mp
483     sub    r0, 2
484
485     movq   m0, [pix_tmp+0x10]
486     movq   m1, [pix_tmp+0x20]
487     lea    r1, [r0+r4]
488     movq   m2, [pix_tmp+0x30]
489     movq   m3, [pix_tmp+0x40]
490     TRANSPOSE8x4B_STORE  PASS8ROWS(r0, r1, r3, r4)
491
492     lea    r0, [r0+r3*8]
493     lea    r1, [r1+r3*8]
494     movq   m0, [pix_tmp+0x18]
495     movq   m1, [pix_tmp+0x28]
496     movq   m2, [pix_tmp+0x38]
497     movq   m3, [pix_tmp+0x48]
498     TRANSPOSE8x4B_STORE  PASS8ROWS(r0, r1, r3, r4)
499
500     RET
501 %endmacro ; DEBLOCK_LUMA
502
503 INIT_MMX mmxext
504 DEBLOCK_LUMA v8, 8
505 INIT_XMM sse2
506 DEBLOCK_LUMA v, 16
507 %if HAVE_AVX_EXTERNAL
508 INIT_XMM avx
509 DEBLOCK_LUMA v, 16
510 %endif
511
512 %endif ; ARCH
513
514
515
516 %macro LUMA_INTRA_P012 4 ; p0..p3 in memory
517 %if ARCH_X86_64
518     pavgb t0, p2, p1
519     pavgb t1, p0, q0
520 %else
521     mova  t0, p2
522     mova  t1, p0
523     pavgb t0, p1
524     pavgb t1, q0
525 %endif
526     pavgb t0, t1 ; ((p2+p1+1)/2 + (p0+q0+1)/2 + 1)/2
527     mova  t5, t1
528 %if ARCH_X86_64
529     paddb t2, p2, p1
530     paddb t3, p0, q0
531 %else
532     mova  t2, p2
533     mova  t3, p0
534     paddb t2, p1
535     paddb t3, q0
536 %endif
537     paddb t2, t3
538     mova  t3, t2
539     mova  t4, t2
540     psrlw t2, 1
541     pavgb t2, mpb_0
542     pxor  t2, t0
543     pand  t2, mpb_1
544     psubb t0, t2 ; p1' = (p2+p1+p0+q0+2)/4;
545
546 %if ARCH_X86_64
547     pavgb t1, p2, q1
548     psubb t2, p2, q1
549 %else
550     mova  t1, p2
551     mova  t2, p2
552     pavgb t1, q1
553     psubb t2, q1
554 %endif
555     paddb t3, t3
556     psubb t3, t2 ; p2+2*p1+2*p0+2*q0+q1
557     pand  t2, mpb_1
558     psubb t1, t2
559     pavgb t1, p1
560     pavgb t1, t5 ; (((p2+q1)/2 + p1+1)/2 + (p0+q0+1)/2 + 1)/2
561     psrlw t3, 2
562     pavgb t3, mpb_0
563     pxor  t3, t1
564     pand  t3, mpb_1
565     psubb t1, t3 ; p0'a = (p2+2*p1+2*p0+2*q0+q1+4)/8
566
567     pxor  t3, p0, q1
568     pavgb t2, p0, q1
569     pand  t3, mpb_1
570     psubb t2, t3
571     pavgb t2, p1 ; p0'b = (2*p1+p0+q0+2)/4
572
573     pxor  t1, t2
574     pxor  t2, p0
575     pand  t1, mask1p
576     pand  t2, mask0
577     pxor  t1, t2
578     pxor  t1, p0
579     mova  %1, t1 ; store p0
580
581     mova  t1, %4 ; p3
582     paddb t2, t1, p2
583     pavgb t1, p2
584     pavgb t1, t0 ; (p3+p2+1)/2 + (p2+p1+p0+q0+2)/4
585     paddb t2, t2
586     paddb t2, t4 ; 2*p3+3*p2+p1+p0+q0
587     psrlw t2, 2
588     pavgb t2, mpb_0
589     pxor  t2, t1
590     pand  t2, mpb_1
591     psubb t1, t2 ; p2' = (2*p3+3*p2+p1+p0+q0+4)/8
592
593     pxor  t0, p1
594     pxor  t1, p2
595     pand  t0, mask1p
596     pand  t1, mask1p
597     pxor  t0, p1
598     pxor  t1, p2
599     mova  %2, t0 ; store p1
600     mova  %3, t1 ; store p2
601 %endmacro
602
603 %macro LUMA_INTRA_SWAP_PQ 0
604     %define q1 m0
605     %define q0 m1
606     %define p0 m2
607     %define p1 m3
608     %define p2 q2
609     %define mask1p mask1q
610 %endmacro
611
612 %macro DEBLOCK_LUMA_INTRA 1
613     %define p1 m0
614     %define p0 m1
615     %define q0 m2
616     %define q1 m3
617     %define t0 m4
618     %define t1 m5
619     %define t2 m6
620     %define t3 m7
621 %if ARCH_X86_64
622     %define p2 m8
623     %define q2 m9
624     %define t4 m10
625     %define t5 m11
626     %define mask0 m12
627     %define mask1p m13
628 %if WIN64
629     %define mask1q [rsp]
630 %else
631     %define mask1q [rsp-24]
632 %endif
633     %define mpb_0 m14
634     %define mpb_1 m15
635 %else
636     %define spill(x) [esp+16*x]
637     %define p2 [r4+r1]
638     %define q2 [r0+2*r1]
639     %define t4 spill(0)
640     %define t5 spill(1)
641     %define mask0 spill(2)
642     %define mask1p spill(3)
643     %define mask1q spill(4)
644     %define mpb_0 [pb_0]
645     %define mpb_1 [pb_1]
646 %endif
647
648 ;-----------------------------------------------------------------------------
649 ; void deblock_v_luma_intra( uint8_t *pix, int stride, int alpha, int beta )
650 ;-----------------------------------------------------------------------------
651 %if WIN64
652 cglobal deblock_%1_luma_intra_8, 4,6,16,0x10
653 %else
654 cglobal deblock_%1_luma_intra_8, 4,6,16,ARCH_X86_64*0x50-0x50
655 %endif
656     lea     r4, [r1*4]
657     lea     r5, [r1*3] ; 3*stride
658     dec     r2d        ; alpha-1
659     jl .end
660     neg     r4
661     dec     r3d        ; beta-1
662     jl .end
663     add     r4, r0     ; pix-4*stride
664     mova    p1, [r4+2*r1]
665     mova    p0, [r4+r5]
666     mova    q0, [r0]
667     mova    q1, [r0+r1]
668 %if ARCH_X86_64
669     pxor    mpb_0, mpb_0
670     mova    mpb_1, [pb_1]
671     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
672     SWAP    7, 12 ; m12=mask0
673     pavgb   t5, mpb_0
674     pavgb   t5, mpb_1 ; alpha/4+1
675     movdqa  p2, [r4+r1]
676     movdqa  q2, [r0+2*r1]
677     DIFF_GT2 p0, q0, t5, t0, t3 ; t0 = |p0-q0| > alpha/4+1
678     DIFF_GT2 p0, p2, m5, t2, t5 ; mask1 = |p2-p0| > beta-1
679     DIFF_GT2 q0, q2, m5, t4, t5 ; t4 = |q2-q0| > beta-1
680     pand    t0, mask0
681     pand    t4, t0
682     pand    t2, t0
683     mova    mask1q, t4
684     mova    mask1p, t2
685 %else
686     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
687     mova    m4, t5
688     mova    mask0, m7
689     pavgb   m4, [pb_0]
690     pavgb   m4, [pb_1] ; alpha/4+1
691     DIFF_GT2 p0, q0, m4, m6, m7 ; m6 = |p0-q0| > alpha/4+1
692     pand    m6, mask0
693     DIFF_GT2 p0, p2, m5, m4, m7 ; m4 = |p2-p0| > beta-1
694     pand    m4, m6
695     mova    mask1p, m4
696     DIFF_GT2 q0, q2, m5, m4, m7 ; m4 = |q2-q0| > beta-1
697     pand    m4, m6
698     mova    mask1q, m4
699 %endif
700     LUMA_INTRA_P012 [r4+r5], [r4+2*r1], [r4+r1], [r4]
701     LUMA_INTRA_SWAP_PQ
702     LUMA_INTRA_P012 [r0], [r0+r1], [r0+2*r1], [r0+r5]
703 .end:
704     RET
705
706 INIT_MMX cpuname
707 %if ARCH_X86_64
708 ;-----------------------------------------------------------------------------
709 ; void deblock_h_luma_intra( uint8_t *pix, int stride, int alpha, int beta )
710 ;-----------------------------------------------------------------------------
711 cglobal deblock_h_luma_intra_8, 4,9
712     movsxd r7,  r1d
713     lea    r8,  [r7*3]
714     lea    r6,  [r0-4]
715     lea    r5,  [r0-4+r8]
716     sub    rsp, 0x88
717     %define pix_tmp rsp
718
719     ; transpose 8x16 -> tmp space
720     TRANSPOSE8x8_MEM  PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
721     lea    r6, [r6+r7*8]
722     lea    r5, [r5+r7*8]
723     TRANSPOSE8x8_MEM  PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
724
725     lea    r0,  [pix_tmp+0x40]
726     mov    r1,  0x10
727     call   deblock_v_luma_intra_8
728
729     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
730     lea    r5, [r6+r8]
731     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8)
732     shl    r7,  3
733     sub    r6,  r7
734     sub    r5,  r7
735     shr    r7,  3
736     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8)
737     add    rsp, 0x88
738     RET
739 %else
740 cglobal deblock_h_luma_intra_8, 2,4,8,0x80
741     lea    r3,  [r1*3]
742     sub    r0,  4
743     lea    r2,  [r0+r3]
744     %define pix_tmp rsp
745
746     ; transpose 8x16 -> tmp space
747     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
748     lea    r0,  [r0+r1*8]
749     lea    r2,  [r2+r1*8]
750     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
751
752     lea    r0,  [pix_tmp+0x40]
753     PUSH   dword r3m
754     PUSH   dword r2m
755     PUSH   dword 16
756     PUSH   r0
757     call   deblock_%1_luma_intra_8
758 %ifidn %1, v8
759     add    dword [rsp], 8 ; pix_tmp+8
760     call   deblock_%1_luma_intra_8
761 %endif
762     ADD    esp, 16
763
764     mov    r1,  r1m
765     mov    r0,  r0mp
766     lea    r3,  [r1*3]
767     sub    r0,  4
768     lea    r2,  [r0+r3]
769     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
770     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
771     lea    r0,  [r0+r1*8]
772     lea    r2,  [r2+r1*8]
773     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
774     RET
775 %endif ; ARCH_X86_64
776 %endmacro ; DEBLOCK_LUMA_INTRA
777
778 INIT_XMM sse2
779 DEBLOCK_LUMA_INTRA v
780 %if HAVE_AVX_EXTERNAL
781 INIT_XMM avx
782 DEBLOCK_LUMA_INTRA v
783 %endif
784 %if ARCH_X86_64 == 0
785 INIT_MMX mmxext
786 DEBLOCK_LUMA_INTRA v8
787 %endif
788
789 INIT_MMX mmxext
790
791 %macro CHROMA_V_START 0
792     dec    r2d      ; alpha-1
793     dec    r3d      ; beta-1
794     mov    t5, r0
795     sub    t5, r1
796     sub    t5, r1
797 %endmacro
798
799 %macro CHROMA_H_START 0
800     dec    r2d
801     dec    r3d
802     sub    r0, 2
803     lea    t6, [r1*3]
804     mov    t5, r0
805     add    r0, t6
806 %endmacro
807
808 %define t5 r5
809 %define t6 r6
810
811 ;-----------------------------------------------------------------------------
812 ; void ff_deblock_v_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
813 ;-----------------------------------------------------------------------------
814 cglobal deblock_v_chroma_8, 5,6
815     CHROMA_V_START
816     movq  m0, [t5]
817     movq  m1, [t5+r1]
818     movq  m2, [r0]
819     movq  m3, [r0+r1]
820     call ff_chroma_inter_body_mmxext
821     movq  [t5+r1], m1
822     movq  [r0], m2
823     RET
824
825 ;-----------------------------------------------------------------------------
826 ; void ff_deblock_h_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
827 ;-----------------------------------------------------------------------------
828 cglobal deblock_h_chroma_8, 5,7
829 %if UNIX64
830     %define buf0 [rsp-24]
831     %define buf1 [rsp-16]
832 %elif WIN64
833     sub   rsp, 16
834     %define buf0 [rsp]
835     %define buf1 [rsp+8]
836 %else
837     %define buf0 r0m
838     %define buf1 r2m
839 %endif
840     CHROMA_H_START
841     TRANSPOSE4x8_LOAD  bw, wd, dq, PASS8ROWS(t5, r0, r1, t6)
842     movq  buf0, m0
843     movq  buf1, m3
844     LOAD_MASK  r2d, r3d
845     movd       m6, [r4] ; tc0
846     punpcklbw  m6, m6
847     pand       m7, m6
848     DEBLOCK_P0_Q0
849     movq  m0, buf0
850     movq  m3, buf1
851     TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6)
852 %if WIN64
853     add   rsp, 16
854 %endif
855     RET
856
857 ALIGN 16
858 ff_chroma_inter_body_mmxext:
859     LOAD_MASK  r2d, r3d
860     movd       m6, [r4] ; tc0
861     punpcklbw  m6, m6
862     pand       m7, m6
863     DEBLOCK_P0_Q0
864     ret
865
866
867
868 ; in: %1=p0 %2=p1 %3=q1
869 ; out: p0 = (p0 + q1 + 2*p1 + 2) >> 2
870 %macro CHROMA_INTRA_P0 3
871     movq    m4, %1
872     pxor    m4, %3
873     pand    m4, [pb_1] ; m4 = (p0^q1)&1
874     pavgb   %1, %3
875     psubusb %1, m4
876     pavgb   %1, %2             ; dst = avg(p1, avg(p0,q1) - ((p0^q1)&1))
877 %endmacro
878
879 %define t5 r4
880 %define t6 r5
881
882 ;-----------------------------------------------------------------------------
883 ; void ff_deblock_v_chroma_intra( uint8_t *pix, int stride, int alpha, int beta )
884 ;-----------------------------------------------------------------------------
885 cglobal deblock_v_chroma_intra_8, 4,5
886     CHROMA_V_START
887     movq  m0, [t5]
888     movq  m1, [t5+r1]
889     movq  m2, [r0]
890     movq  m3, [r0+r1]
891     call ff_chroma_intra_body_mmxext
892     movq  [t5+r1], m1
893     movq  [r0], m2
894     RET
895
896 ;-----------------------------------------------------------------------------
897 ; void ff_deblock_h_chroma_intra( uint8_t *pix, int stride, int alpha, int beta )
898 ;-----------------------------------------------------------------------------
899 cglobal deblock_h_chroma_intra_8, 4,6
900     CHROMA_H_START
901     TRANSPOSE4x8_LOAD  bw, wd, dq, PASS8ROWS(t5, r0, r1, t6)
902     call ff_chroma_intra_body_mmxext
903     TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6)
904     RET
905
906 ALIGN 16
907 ff_chroma_intra_body_mmxext:
908     LOAD_MASK r2d, r3d
909     movq   m5, m1
910     movq   m6, m2
911     CHROMA_INTRA_P0  m1, m0, m3
912     CHROMA_INTRA_P0  m2, m3, m0
913     psubb  m1, m5
914     psubb  m2, m6
915     pand   m1, m7
916     pand   m2, m7
917     paddb  m1, m5
918     paddb  m2, m6
919     ret
920
921 ;-----------------------------------------------------------------------------
922 ; void h264_loop_filter_strength(int16_t bs[2][4][4], uint8_t nnz[40],
923 ;                                int8_t ref[2][40], int16_t mv[2][40][2],
924 ;                                int bidir,    int edges,    int step,
925 ;                                int mask_mv0, int mask_mv1, int field);
926 ;
927 ; bidir    is 0 or 1
928 ; edges    is 1 or 4
929 ; step     is 1 or 2
930 ; mask_mv0 is 0 or 3
931 ; mask_mv1 is 0 or 1
932 ; field    is 0 or 1
933 ;-----------------------------------------------------------------------------
934 %macro loop_filter_strength_iteration 7 ; edges, step, mask_mv,
935                                         ; dir, d_idx, mask_dir, bidir
936 %define edgesd    %1
937 %define stepd     %2
938 %define mask_mvd  %3
939 %define dir       %4
940 %define d_idx     %5
941 %define mask_dir  %6
942 %define bidir     %7
943     xor          b_idxd, b_idxd ; for (b_idx = 0; b_idx < edges; b_idx += step)
944 %%.b_idx_loop:
945 %if mask_dir == 0
946     pxor             m0, m0
947 %endif
948     test         b_idxd, dword mask_mvd
949     jnz %%.skip_loop_iter                       ; if (!(b_idx & mask_mv))
950 %if bidir == 1
951     movd             m2, [refq+b_idxq+d_idx+12] ; { ref0[bn] }
952     punpckldq        m2, [refq+b_idxq+d_idx+52] ; { ref0[bn], ref1[bn] }
953     pshufw           m0, [refq+b_idxq+12], 0x44 ; { ref0[b],  ref0[b]  }
954     pshufw           m1, [refq+b_idxq+52], 0x44 ; { ref1[b],  ref1[b]  }
955     pshufw           m3, m2, 0x4E               ; { ref1[bn], ref0[bn] }
956     psubb            m0, m2                     ; { ref0[b] != ref0[bn],
957                                                 ;   ref0[b] != ref1[bn] }
958     psubb            m1, m3                     ; { ref1[b] != ref1[bn],
959                                                 ;   ref1[b] != ref0[bn] }
960
961     por              m0, m1
962     mova             m1, [mvq+b_idxq*4+(d_idx+12)*4]
963     mova             m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
964     mova             m3, m1
965     mova             m4, m2
966     psubw            m1, [mvq+b_idxq*4+12*4]
967     psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
968     psubw            m3, [mvq+b_idxq*4+52*4]
969     psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
970     packsswb         m1, m2
971     packsswb         m3, m4
972     paddb            m1, m6
973     paddb            m3, m6
974     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
975     psubusb          m3, m5
976     packsswb         m1, m3
977
978     por              m0, m1
979     mova             m1, [mvq+b_idxq*4+(d_idx+52)*4]
980     mova             m2, [mvq+b_idxq*4+(d_idx+52)*4+mmsize]
981     mova             m3, m1
982     mova             m4, m2
983     psubw            m1, [mvq+b_idxq*4+12*4]
984     psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
985     psubw            m3, [mvq+b_idxq*4+52*4]
986     psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
987     packsswb         m1, m2
988     packsswb         m3, m4
989     paddb            m1, m6
990     paddb            m3, m6
991     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
992     psubusb          m3, m5
993     packsswb         m1, m3
994
995     pshufw           m1, m1, 0x4E
996     por              m0, m1
997     pshufw           m1, m0, 0x4E
998     pminub           m0, m1
999 %else ; bidir == 0
1000     movd             m0, [refq+b_idxq+12]
1001     psubb            m0, [refq+b_idxq+d_idx+12] ; ref[b] != ref[bn]
1002
1003     mova             m1, [mvq+b_idxq*4+12*4]
1004     mova             m2, [mvq+b_idxq*4+12*4+mmsize]
1005     psubw            m1, [mvq+b_idxq*4+(d_idx+12)*4]
1006     psubw            m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
1007     packsswb         m1, m2
1008     paddb            m1, m6
1009     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
1010     packsswb         m1, m1
1011     por              m0, m1
1012 %endif ; bidir == 1/0
1013
1014 %%.skip_loop_iter:
1015     movd             m1, [nnzq+b_idxq+12]
1016     por              m1, [nnzq+b_idxq+d_idx+12] ; nnz[b] || nnz[bn]
1017
1018     pminub           m1, m7
1019     pminub           m0, m7
1020     psllw            m1, 1
1021     pxor             m2, m2
1022     pmaxub           m1, m0
1023     punpcklbw        m1, m2
1024     movq [bsq+b_idxq+32*dir], m1
1025
1026     add          b_idxd, dword stepd
1027     cmp          b_idxd, dword edgesd
1028     jl %%.b_idx_loop
1029 %endmacro
1030
1031 INIT_MMX mmxext
1032 cglobal h264_loop_filter_strength, 9, 9, 0, bs, nnz, ref, mv, bidir, edges, \
1033                                             step, mask_mv0, mask_mv1, field
1034 %define b_idxq bidirq
1035 %define b_idxd bidird
1036     cmp    dword fieldm, 0
1037     mova             m7, [pb_1]
1038     mova             m5, [pb_3]
1039     je .nofield
1040     mova             m5, [pb_3_1]
1041 .nofield:
1042     mova             m6, m5
1043     paddb            m5, m5
1044
1045     shl     dword stepd, 3
1046     shl    dword edgesd, 3
1047 %if ARCH_X86_32
1048 %define mask_mv0d mask_mv0m
1049 %define mask_mv1d mask_mv1m
1050 %endif
1051     shl dword mask_mv1d, 3
1052     shl dword mask_mv0d, 3
1053
1054     cmp    dword bidird, 0
1055     jne .bidir
1056     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 0
1057     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 0
1058
1059     mova             m0, [bsq+mmsize*0]
1060     mova             m1, [bsq+mmsize*1]
1061     mova             m2, [bsq+mmsize*2]
1062     mova             m3, [bsq+mmsize*3]
1063     TRANSPOSE4x4W 0, 1, 2, 3, 4
1064     mova  [bsq+mmsize*0], m0
1065     mova  [bsq+mmsize*1], m1
1066     mova  [bsq+mmsize*2], m2
1067     mova  [bsq+mmsize*3], m3
1068     RET
1069
1070 .bidir:
1071     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 1
1072     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 1
1073
1074     mova             m0, [bsq+mmsize*0]
1075     mova             m1, [bsq+mmsize*1]
1076     mova             m2, [bsq+mmsize*2]
1077     mova             m3, [bsq+mmsize*3]
1078     TRANSPOSE4x4W 0, 1, 2, 3, 4
1079     mova  [bsq+mmsize*0], m0
1080     mova  [bsq+mmsize*1], m1
1081     mova  [bsq+mmsize*2], m2
1082     mova  [bsq+mmsize*3], m3
1083     RET