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