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