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