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