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