Merge commit '6860b4081d046558c44b1b42f22022ea341a2a73'
[ffmpeg.git] / 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_3_1: times 4 db 3, 1
32
33 SECTION .text
34
35 cextern pb_0
36 cextern pb_1
37 cextern pb_3
38 cextern pb_A1
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
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     %assign pad 2*%2+12-(stack_offset&15)
410     SUB     esp, pad
411
412     mova    m0, [r4+r1]   ; p1
413     mova    m1, [r4+2*r1] ; p0
414     mova    m2, [r0]      ; q0
415     mova    m3, [r0+r1]   ; q1
416     LOAD_MASK r2, r3
417
418     mov     r3, r4mp
419     pcmpeqb m3, m3
420     movd    m4, [r3] ; tc0
421     punpcklbw m4, m4
422     punpcklbw m4, m4 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
423     mova   [esp+%2], m4 ; tc
424     pcmpgtb m4, m3
425     mova    m3, [r4] ; p2
426     pand    m4, m7
427     mova   [esp], m4 ; mask
428
429     DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1
430     pand    m6, m4
431     pand    m4, [esp+%2] ; tc
432     psubb   m7, m4, m6
433     pand    m6, m4
434     LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4
435
436     mova    m4, [r0+2*r1] ; q2
437     DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1
438     pand    m6, [esp] ; mask
439     mova    m5, [esp+%2] ; tc
440     psubb   m7, m6
441     pand    m5, m6
442     mova    m3, [r0+r1]
443     LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m5, m6
444
445     DEBLOCK_P0_Q0
446     mova    [r4+2*r1], m1
447     mova    [r0], m2
448     ADD     esp, pad
449     RET
450
451 ;-----------------------------------------------------------------------------
452 ; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
453 ;-----------------------------------------------------------------------------
454 INIT_MMX cpuname
455 cglobal deblock_h_luma_8, 0,5
456     mov    r0, r0mp
457     mov    r3, r1m
458     lea    r4, [r3*3]
459     sub    r0, 4
460     lea    r1, [r0+r4]
461     %assign pad 0x78-(stack_offset&15)
462     SUB    esp, pad
463 %define pix_tmp esp+12
464
465     ; transpose 6x16 -> tmp space
466     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp
467     lea    r0, [r0+r3*8]
468     lea    r1, [r1+r3*8]
469     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp+8
470
471     ; vertical filter
472     lea    r0, [pix_tmp+0x30]
473     PUSH   dword r4m
474     PUSH   dword r3m
475     PUSH   dword r2m
476     PUSH   dword 16
477     PUSH   dword r0
478     call   deblock_%1_luma_8
479 %ifidn %1, v8
480     add    dword [esp   ], 8 ; pix_tmp+0x38
481     add    dword [esp+16], 2 ; tc0+2
482     call   deblock_%1_luma_8
483 %endif
484     ADD    esp, 20
485
486     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)
487     mov    r0, r0mp
488     sub    r0, 2
489
490     movq   m0, [pix_tmp+0x10]
491     movq   m1, [pix_tmp+0x20]
492     lea    r1, [r0+r4]
493     movq   m2, [pix_tmp+0x30]
494     movq   m3, [pix_tmp+0x40]
495     TRANSPOSE8x4B_STORE  PASS8ROWS(r0, r1, r3, r4)
496
497     lea    r0, [r0+r3*8]
498     lea    r1, [r1+r3*8]
499     movq   m0, [pix_tmp+0x18]
500     movq   m1, [pix_tmp+0x28]
501     movq   m2, [pix_tmp+0x38]
502     movq   m3, [pix_tmp+0x48]
503     TRANSPOSE8x4B_STORE  PASS8ROWS(r0, r1, r3, r4)
504
505     ADD    esp, pad
506     RET
507 %endmacro ; DEBLOCK_LUMA
508
509 INIT_MMX mmx2
510 DEBLOCK_LUMA v8, 8
511 INIT_XMM sse2
512 DEBLOCK_LUMA v, 16
513 %if HAVE_AVX_EXTERNAL
514 INIT_XMM avx
515 DEBLOCK_LUMA v, 16
516 %endif
517
518 %endif ; ARCH
519
520
521
522 %macro LUMA_INTRA_P012 4 ; p0..p3 in memory
523 %if ARCH_X86_64
524     pavgb t0, p2, p1
525     pavgb t1, p0, q0
526 %else
527     mova  t0, p2
528     mova  t1, p0
529     pavgb t0, p1
530     pavgb t1, q0
531 %endif
532     pavgb t0, t1 ; ((p2+p1+1)/2 + (p0+q0+1)/2 + 1)/2
533     mova  t5, t1
534 %if ARCH_X86_64
535     paddb t2, p2, p1
536     paddb t3, p0, q0
537 %else
538     mova  t2, p2
539     mova  t3, p0
540     paddb t2, p1
541     paddb t3, q0
542 %endif
543     paddb t2, t3
544     mova  t3, t2
545     mova  t4, t2
546     psrlw t2, 1
547     pavgb t2, mpb_0
548     pxor  t2, t0
549     pand  t2, mpb_1
550     psubb t0, t2 ; p1' = (p2+p1+p0+q0+2)/4;
551
552 %if ARCH_X86_64
553     pavgb t1, p2, q1
554     psubb t2, p2, q1
555 %else
556     mova  t1, p2
557     mova  t2, p2
558     pavgb t1, q1
559     psubb t2, q1
560 %endif
561     paddb t3, t3
562     psubb t3, t2 ; p2+2*p1+2*p0+2*q0+q1
563     pand  t2, mpb_1
564     psubb t1, t2
565     pavgb t1, p1
566     pavgb t1, t5 ; (((p2+q1)/2 + p1+1)/2 + (p0+q0+1)/2 + 1)/2
567     psrlw t3, 2
568     pavgb t3, mpb_0
569     pxor  t3, t1
570     pand  t3, mpb_1
571     psubb t1, t3 ; p0'a = (p2+2*p1+2*p0+2*q0+q1+4)/8
572
573     pxor  t3, p0, q1
574     pavgb t2, p0, q1
575     pand  t3, mpb_1
576     psubb t2, t3
577     pavgb t2, p1 ; p0'b = (2*p1+p0+q0+2)/4
578
579     pxor  t1, t2
580     pxor  t2, p0
581     pand  t1, mask1p
582     pand  t2, mask0
583     pxor  t1, t2
584     pxor  t1, p0
585     mova  %1, t1 ; store p0
586
587     mova  t1, %4 ; p3
588     paddb t2, t1, p2
589     pavgb t1, p2
590     pavgb t1, t0 ; (p3+p2+1)/2 + (p2+p1+p0+q0+2)/4
591     paddb t2, t2
592     paddb t2, t4 ; 2*p3+3*p2+p1+p0+q0
593     psrlw t2, 2
594     pavgb t2, mpb_0
595     pxor  t2, t1
596     pand  t2, mpb_1
597     psubb t1, t2 ; p2' = (2*p3+3*p2+p1+p0+q0+4)/8
598
599     pxor  t0, p1
600     pxor  t1, p2
601     pand  t0, mask1p
602     pand  t1, mask1p
603     pxor  t0, p1
604     pxor  t1, p2
605     mova  %2, t0 ; store p1
606     mova  %3, t1 ; store p2
607 %endmacro
608
609 %macro LUMA_INTRA_SWAP_PQ 0
610     %define q1 m0
611     %define q0 m1
612     %define p0 m2
613     %define p1 m3
614     %define p2 q2
615     %define mask1p mask1q
616 %endmacro
617
618 %macro DEBLOCK_LUMA_INTRA 1
619     %define p1 m0
620     %define p0 m1
621     %define q0 m2
622     %define q1 m3
623     %define t0 m4
624     %define t1 m5
625     %define t2 m6
626     %define t3 m7
627 %if ARCH_X86_64
628     %define p2 m8
629     %define q2 m9
630     %define t4 m10
631     %define t5 m11
632     %define mask0 m12
633     %define mask1p m13
634     %define mask1q [rsp-24]
635     %define mpb_0 m14
636     %define mpb_1 m15
637 %else
638     %define spill(x) [esp+16*x+((stack_offset+4)&15)]
639     %define p2 [r4+r1]
640     %define q2 [r0+2*r1]
641     %define t4 spill(0)
642     %define t5 spill(1)
643     %define mask0 spill(2)
644     %define mask1p spill(3)
645     %define mask1q spill(4)
646     %define mpb_0 [pb_0]
647     %define mpb_1 [pb_1]
648 %endif
649
650 ;-----------------------------------------------------------------------------
651 ; void deblock_v_luma_intra( uint8_t *pix, int stride, int alpha, int beta )
652 ;-----------------------------------------------------------------------------
653 cglobal deblock_%1_luma_intra_8, 4,6,16
654 %if ARCH_X86_64 == 0
655     sub     esp, 0x60
656 %endif
657     lea     r4, [r1*4]
658     lea     r5, [r1*3] ; 3*stride
659     dec     r2d        ; alpha-1
660     jl .end
661     neg     r4
662     dec     r3d        ; beta-1
663     jl .end
664     add     r4, r0     ; pix-4*stride
665     mova    p1, [r4+2*r1]
666     mova    p0, [r4+r5]
667     mova    q0, [r0]
668     mova    q1, [r0+r1]
669 %if ARCH_X86_64
670     pxor    mpb_0, mpb_0
671     mova    mpb_1, [pb_1]
672     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
673     SWAP    7, 12 ; m12=mask0
674     pavgb   t5, mpb_0
675     pavgb   t5, mpb_1 ; alpha/4+1
676     movdqa  p2, [r4+r1]
677     movdqa  q2, [r0+2*r1]
678     DIFF_GT2 p0, q0, t5, t0, t3 ; t0 = |p0-q0| > alpha/4+1
679     DIFF_GT2 p0, p2, m5, t2, t5 ; mask1 = |p2-p0| > beta-1
680     DIFF_GT2 q0, q2, m5, t4, t5 ; t4 = |q2-q0| > beta-1
681     pand    t0, mask0
682     pand    t4, t0
683     pand    t2, t0
684     mova    mask1q, t4
685     mova    mask1p, t2
686 %else
687     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
688     mova    m4, t5
689     mova    mask0, m7
690     pavgb   m4, [pb_0]
691     pavgb   m4, [pb_1] ; alpha/4+1
692     DIFF_GT2 p0, q0, m4, m6, m7 ; m6 = |p0-q0| > alpha/4+1
693     pand    m6, mask0
694     DIFF_GT2 p0, p2, m5, m4, m7 ; m4 = |p2-p0| > beta-1
695     pand    m4, m6
696     mova    mask1p, m4
697     DIFF_GT2 q0, q2, m5, m4, m7 ; m4 = |q2-q0| > beta-1
698     pand    m4, m6
699     mova    mask1q, m4
700 %endif
701     LUMA_INTRA_P012 [r4+r5], [r4+2*r1], [r4+r1], [r4]
702     LUMA_INTRA_SWAP_PQ
703     LUMA_INTRA_P012 [r0], [r0+r1], [r0+2*r1], [r0+r5]
704 .end:
705 %if ARCH_X86_64 == 0
706     add     esp, 0x60
707 %endif
708     RET
709
710 INIT_MMX cpuname
711 %if ARCH_X86_64
712 ;-----------------------------------------------------------------------------
713 ; void deblock_h_luma_intra( uint8_t *pix, int stride, int alpha, int beta )
714 ;-----------------------------------------------------------------------------
715 cglobal deblock_h_luma_intra_8, 4,9
716     movsxd r7,  r1d
717     lea    r8,  [r7*3]
718     lea    r6,  [r0-4]
719     lea    r5,  [r0-4+r8]
720     sub    rsp, 0x88
721     %define pix_tmp rsp
722
723     ; transpose 8x16 -> tmp space
724     TRANSPOSE8x8_MEM  PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
725     lea    r6, [r6+r7*8]
726     lea    r5, [r5+r7*8]
727     TRANSPOSE8x8_MEM  PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
728
729     lea    r0,  [pix_tmp+0x40]
730     mov    r1,  0x10
731     call   deblock_v_luma_intra_8
732
733     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
734     lea    r5, [r6+r8]
735     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8)
736     shl    r7,  3
737     sub    r6,  r7
738     sub    r5,  r7
739     shr    r7,  3
740     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8)
741     add    rsp, 0x88
742     RET
743 %else
744 cglobal deblock_h_luma_intra_8, 2,4
745     lea    r3,  [r1*3]
746     sub    r0,  4
747     lea    r2,  [r0+r3]
748 %assign pad 0x8c-(stack_offset&15)
749     SUB    rsp, pad
750     %define pix_tmp rsp
751
752     ; transpose 8x16 -> tmp space
753     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
754     lea    r0,  [r0+r1*8]
755     lea    r2,  [r2+r1*8]
756     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
757
758     lea    r0,  [pix_tmp+0x40]
759     PUSH   dword r3m
760     PUSH   dword r2m
761     PUSH   dword 16
762     PUSH   r0
763     call   deblock_%1_luma_intra_8
764 %ifidn %1, v8
765     add    dword [rsp], 8 ; pix_tmp+8
766     call   deblock_%1_luma_intra_8
767 %endif
768     ADD    esp, 16
769
770     mov    r1,  r1m
771     mov    r0,  r0mp
772     lea    r3,  [r1*3]
773     sub    r0,  4
774     lea    r2,  [r0+r3]
775     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
776     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
777     lea    r0,  [r0+r1*8]
778     lea    r2,  [r2+r1*8]
779     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
780     ADD    rsp, pad
781     RET
782 %endif ; ARCH_X86_64
783 %endmacro ; DEBLOCK_LUMA_INTRA
784
785 INIT_XMM sse2
786 DEBLOCK_LUMA_INTRA v
787 %if HAVE_AVX_EXTERNAL
788 INIT_XMM avx
789 DEBLOCK_LUMA_INTRA v
790 %endif
791 %if ARCH_X86_64 == 0
792 INIT_MMX mmx2
793 DEBLOCK_LUMA_INTRA v8
794 %endif
795
796 INIT_MMX mmx2
797
798 %macro CHROMA_V_START 0
799     dec    r2d      ; alpha-1
800     dec    r3d      ; beta-1
801     mov    t5, r0
802     sub    t5, r1
803     sub    t5, r1
804 %endmacro
805
806 %macro CHROMA_H_START 0
807     dec    r2d
808     dec    r3d
809     sub    r0, 2
810     lea    t6, [r1*3]
811     mov    t5, r0
812     add    r0, t6
813 %endmacro
814
815 %define t5 r5
816 %define t6 r6
817
818 ;-----------------------------------------------------------------------------
819 ; void ff_deblock_v_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
820 ;-----------------------------------------------------------------------------
821 cglobal deblock_v_chroma_8, 5,6
822     CHROMA_V_START
823     movq  m0, [t5]
824     movq  m1, [t5+r1]
825     movq  m2, [r0]
826     movq  m3, [r0+r1]
827     call ff_chroma_inter_body_mmx2
828     movq  [t5+r1], m1
829     movq  [r0], m2
830     RET
831
832 ;-----------------------------------------------------------------------------
833 ; void ff_deblock_h_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
834 ;-----------------------------------------------------------------------------
835 cglobal deblock_h_chroma_8, 5,7
836 %if UNIX64
837     %define buf0 [rsp-24]
838     %define buf1 [rsp-16]
839 %elif WIN64
840     sub   rsp, 16
841     %define buf0 [rsp]
842     %define buf1 [rsp+8]
843 %else
844     %define buf0 r0m
845     %define buf1 r2m
846 %endif
847     CHROMA_H_START
848     TRANSPOSE4x8_LOAD  bw, wd, dq, PASS8ROWS(t5, r0, r1, t6)
849     movq  buf0, m0
850     movq  buf1, m3
851     LOAD_MASK  r2d, r3d
852     movd       m6, [r4] ; tc0
853     punpcklbw  m6, m6
854     pand       m7, m6
855     DEBLOCK_P0_Q0
856     movq  m0, buf0
857     movq  m3, buf1
858     TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6)
859 %if WIN64
860     add   rsp, 16
861 %endif
862     RET
863
864 ALIGN 16
865 ff_chroma_inter_body_mmx2:
866     LOAD_MASK  r2d, r3d
867     movd       m6, [r4] ; tc0
868     punpcklbw  m6, m6
869     pand       m7, m6
870     DEBLOCK_P0_Q0
871     ret
872
873
874
875 ; in: %1=p0 %2=p1 %3=q1
876 ; out: p0 = (p0 + q1 + 2*p1 + 2) >> 2
877 %macro CHROMA_INTRA_P0 3
878     movq    m4, %1
879     pxor    m4, %3
880     pand    m4, [pb_1] ; m4 = (p0^q1)&1
881     pavgb   %1, %3
882     psubusb %1, m4
883     pavgb   %1, %2             ; dst = avg(p1, avg(p0,q1) - ((p0^q1)&1))
884 %endmacro
885
886 %define t5 r4
887 %define t6 r5
888
889 ;-----------------------------------------------------------------------------
890 ; void ff_deblock_v_chroma_intra( uint8_t *pix, int stride, int alpha, int beta )
891 ;-----------------------------------------------------------------------------
892 cglobal deblock_v_chroma_intra_8, 4,5
893     CHROMA_V_START
894     movq  m0, [t5]
895     movq  m1, [t5+r1]
896     movq  m2, [r0]
897     movq  m3, [r0+r1]
898     call ff_chroma_intra_body_mmx2
899     movq  [t5+r1], m1
900     movq  [r0], m2
901     RET
902
903 ;-----------------------------------------------------------------------------
904 ; void ff_deblock_h_chroma_intra( uint8_t *pix, int stride, int alpha, int beta )
905 ;-----------------------------------------------------------------------------
906 cglobal deblock_h_chroma_intra_8, 4,6
907     CHROMA_H_START
908     TRANSPOSE4x8_LOAD  bw, wd, dq, PASS8ROWS(t5, r0, r1, t6)
909     call ff_chroma_intra_body_mmx2
910     TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6)
911     RET
912
913 ALIGN 16
914 ff_chroma_intra_body_mmx2:
915     LOAD_MASK r2d, r3d
916     movq   m5, m1
917     movq   m6, m2
918     CHROMA_INTRA_P0  m1, m0, m3
919     CHROMA_INTRA_P0  m2, m3, m0
920     psubb  m1, m5
921     psubb  m2, m6
922     pand   m1, m7
923     pand   m2, m7
924     paddb  m1, m5
925     paddb  m2, m6
926     ret
927
928 ;-----------------------------------------------------------------------------
929 ; void h264_loop_filter_strength(int16_t bs[2][4][4], uint8_t nnz[40],
930 ;                                int8_t ref[2][40], int16_t mv[2][40][2],
931 ;                                int bidir,    int edges,    int step,
932 ;                                int mask_mv0, int mask_mv1, int field);
933 ;
934 ; bidir    is 0 or 1
935 ; edges    is 1 or 4
936 ; step     is 1 or 2
937 ; mask_mv0 is 0 or 3
938 ; mask_mv1 is 0 or 1
939 ; field    is 0 or 1
940 ;-----------------------------------------------------------------------------
941 %macro loop_filter_strength_iteration 7 ; edges, step, mask_mv,
942                                         ; dir, d_idx, mask_dir, bidir
943 %define edgesd    %1
944 %define stepd     %2
945 %define mask_mvd  %3
946 %define dir       %4
947 %define d_idx     %5
948 %define mask_dir  %6
949 %define bidir     %7
950     xor          b_idxd, b_idxd ; for (b_idx = 0; b_idx < edges; b_idx += step)
951 %%.b_idx_loop:
952 %if mask_dir == 0
953     pxor             m0, m0
954 %endif
955     test         b_idxd, dword mask_mvd
956     jnz %%.skip_loop_iter                       ; if (!(b_idx & mask_mv))
957 %if bidir == 1
958     movd             m2, [refq+b_idxq+d_idx+12] ; { ref0[bn] }
959     punpckldq        m2, [refq+b_idxq+d_idx+52] ; { ref0[bn], ref1[bn] }
960     pshufw           m0, [refq+b_idxq+12], 0x44 ; { ref0[b],  ref0[b]  }
961     pshufw           m1, [refq+b_idxq+52], 0x44 ; { ref1[b],  ref1[b]  }
962     pshufw           m3, m2, 0x4E               ; { ref1[bn], ref0[bn] }
963     psubb            m0, m2                     ; { ref0[b] != ref0[bn],
964                                                 ;   ref0[b] != ref1[bn] }
965     psubb            m1, m3                     ; { ref1[b] != ref1[bn],
966                                                 ;   ref1[b] != ref0[bn] }
967
968     por              m0, m1
969     mova             m1, [mvq+b_idxq*4+(d_idx+12)*4]
970     mova             m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
971     mova             m3, m1
972     mova             m4, m2
973     psubw            m1, [mvq+b_idxq*4+12*4]
974     psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
975     psubw            m3, [mvq+b_idxq*4+52*4]
976     psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
977     packsswb         m1, m2
978     packsswb         m3, m4
979     paddb            m1, m6
980     paddb            m3, m6
981     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
982     psubusb          m3, m5
983     packsswb         m1, m3
984
985     por              m0, m1
986     mova             m1, [mvq+b_idxq*4+(d_idx+52)*4]
987     mova             m2, [mvq+b_idxq*4+(d_idx+52)*4+mmsize]
988     mova             m3, m1
989     mova             m4, m2
990     psubw            m1, [mvq+b_idxq*4+12*4]
991     psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
992     psubw            m3, [mvq+b_idxq*4+52*4]
993     psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
994     packsswb         m1, m2
995     packsswb         m3, m4
996     paddb            m1, m6
997     paddb            m3, m6
998     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
999     psubusb          m3, m5
1000     packsswb         m1, m3
1001
1002     pshufw           m1, m1, 0x4E
1003     por              m0, m1
1004     pshufw           m1, m0, 0x4E
1005     pminub           m0, m1
1006 %else ; bidir == 0
1007     movd             m0, [refq+b_idxq+12]
1008     psubb            m0, [refq+b_idxq+d_idx+12] ; ref[b] != ref[bn]
1009
1010     mova             m1, [mvq+b_idxq*4+12*4]
1011     mova             m2, [mvq+b_idxq*4+12*4+mmsize]
1012     psubw            m1, [mvq+b_idxq*4+(d_idx+12)*4]
1013     psubw            m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
1014     packsswb         m1, m2
1015     paddb            m1, m6
1016     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
1017     packsswb         m1, m1
1018     por              m0, m1
1019 %endif ; bidir == 1/0
1020
1021 %%.skip_loop_iter:
1022     movd             m1, [nnzq+b_idxq+12]
1023     por              m1, [nnzq+b_idxq+d_idx+12] ; nnz[b] || nnz[bn]
1024
1025     pminub           m1, m7
1026     pminub           m0, m7
1027     psllw            m1, 1
1028     pxor             m2, m2
1029     pmaxub           m1, m0
1030     punpcklbw        m1, m2
1031     movq [bsq+b_idxq+32*dir], m1
1032
1033     add          b_idxd, dword stepd
1034     cmp          b_idxd, dword edgesd
1035     jl %%.b_idx_loop
1036 %endmacro
1037
1038 INIT_MMX mmx2
1039 cglobal h264_loop_filter_strength, 9, 9, 0, bs, nnz, ref, mv, bidir, edges, \
1040                                             step, mask_mv0, mask_mv1, field
1041 %define b_idxq bidirq
1042 %define b_idxd bidird
1043     cmp    dword fieldm, 0
1044     mova             m7, [pb_1]
1045     mova             m5, [pb_3]
1046     je .nofield
1047     mova             m5, [pb_3_1]
1048 .nofield:
1049     mova             m6, m5
1050     paddb            m5, m5
1051
1052     shl     dword stepd, 3
1053     shl    dword edgesd, 3
1054 %if ARCH_X86_32
1055 %define mask_mv0d mask_mv0m
1056 %define mask_mv1d mask_mv1m
1057 %endif
1058     shl dword mask_mv1d, 3
1059     shl dword mask_mv0d, 3
1060
1061     cmp    dword bidird, 0
1062     jne .bidir
1063     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 0
1064     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 0
1065
1066     mova             m0, [bsq+mmsize*0]
1067     mova             m1, [bsq+mmsize*1]
1068     mova             m2, [bsq+mmsize*2]
1069     mova             m3, [bsq+mmsize*3]
1070     TRANSPOSE4x4W 0, 1, 2, 3, 4
1071     mova  [bsq+mmsize*0], m0
1072     mova  [bsq+mmsize*1], m1
1073     mova  [bsq+mmsize*2], m2
1074     mova  [bsq+mmsize*3], m3
1075     RET
1076
1077 .bidir:
1078     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 1
1079     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 1
1080
1081     mova             m0, [bsq+mmsize*0]
1082     mova             m1, [bsq+mmsize*1]
1083     mova             m2, [bsq+mmsize*2]
1084     mova             m3, [bsq+mmsize*3]
1085     TRANSPOSE4x4W 0, 1, 2, 3, 4
1086     mova  [bsq+mmsize*0], m0
1087     mova  [bsq+mmsize*1], m1
1088     mova  [bsq+mmsize*2], m2
1089     mova  [bsq+mmsize*3], m3
1090     RET