Offer an option (disabled by default) to enable the copy of the frames before
[ffmpeg.git] / libavcodec / i386 / h264_deblock_sse2.asm
1 ;*****************************************************************************\r
2 ;* deblock-a.asm: h264 encoder library\r
3 ;*****************************************************************************\r
4 ;* Copyright (C) 2005-2008 x264 project\r
5 ;*\r
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>\r
7 ;*\r
8 ;* This program is free software; you can redistribute it and/or modify\r
9 ;* it under the terms of the GNU General Public License as published by\r
10 ;* the Free Software Foundation; either version 2 of the License, or\r
11 ;* (at your option) any later version.\r
12 ;*\r
13 ;* This program is distributed in the hope that it will be useful,\r
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16 ;* GNU General Public License for more details.\r
17 ;*\r
18 ;* You should have received a copy of the GNU General Public License\r
19 ;* along with this program; if not, write to the Free Software\r
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\r
21 ;*****************************************************************************\r
22 \r
23 %include "x86inc.asm"\r
24 \r
25 SECTION_RODATA\r
26 pb_00: times 16 db 0x00\r
27 pb_01: times 16 db 0x01\r
28 pb_03: times 16 db 0x03\r
29 pb_a1: times 16 db 0xa1\r
30 \r
31 SECTION .text\r
32 \r
33 ; expands to [base],...,[base+7*stride]\r
34 %define PASS8ROWS(base, base3, stride, stride3) \\r
35     [base], [base+stride], [base+stride*2], [base3], \\r
36     [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4]\r
37 \r
38 ; in: 8 rows of 4 bytes in %1..%8\r
39 ; out: 4 rows of 8 bytes in m0..m3\r
40 %macro TRANSPOSE4x8_LOAD 8\r
41     movd       m0, %1\r
42     movd       m2, %2\r
43     movd       m1, %3\r
44     movd       m3, %4\r
45     punpcklbw  m0, m2\r
46     punpcklbw  m1, m3\r
47     movq       m2, m0\r
48     punpcklwd  m0, m1\r
49     punpckhwd  m2, m1\r
50 \r
51     movd       m4, %5\r
52     movd       m6, %6\r
53     movd       m5, %7\r
54     movd       m7, %8\r
55     punpcklbw  m4, m6\r
56     punpcklbw  m5, m7\r
57     movq       m6, m4\r
58     punpcklwd  m4, m5\r
59     punpckhwd  m6, m5\r
60 \r
61     movq       m1, m0\r
62     movq       m3, m2\r
63     punpckldq  m0, m4\r
64     punpckhdq  m1, m4\r
65     punpckldq  m2, m6\r
66     punpckhdq  m3, m6\r
67 %endmacro\r
68 \r
69 ; in: 4 rows of 8 bytes in m0..m3\r
70 ; out: 8 rows of 4 bytes in %1..%8\r
71 %macro TRANSPOSE8x4_STORE 8\r
72     movq       m4, m0\r
73     movq       m5, m1\r
74     movq       m6, m2\r
75     punpckhdq  m4, m4\r
76     punpckhdq  m5, m5\r
77     punpckhdq  m6, m6\r
78 \r
79     punpcklbw  m0, m1\r
80     punpcklbw  m2, m3\r
81     movq       m1, m0\r
82     punpcklwd  m0, m2\r
83     punpckhwd  m1, m2\r
84     movd       %1, m0\r
85     punpckhdq  m0, m0\r
86     movd       %2, m0\r
87     movd       %3, m1\r
88     punpckhdq  m1, m1\r
89     movd       %4, m1\r
90 \r
91     punpckhdq  m3, m3\r
92     punpcklbw  m4, m5\r
93     punpcklbw  m6, m3\r
94     movq       m5, m4\r
95     punpcklwd  m4, m6\r
96     punpckhwd  m5, m6\r
97     movd       %5, m4\r
98     punpckhdq  m4, m4\r
99     movd       %6, m4\r
100     movd       %7, m5\r
101     punpckhdq  m5, m5\r
102     movd       %8, m5\r
103 %endmacro\r
104 \r
105 %macro SBUTTERFLY 4\r
106     movq       %4, %2\r
107     punpckl%1  %2, %3\r
108     punpckh%1  %4, %3\r
109 %endmacro\r
110 \r
111 ; in: 8 rows of 8 (only the middle 6 pels are used) in %1..%8\r
112 ; out: 6 rows of 8 in [%9+0*16] .. [%9+5*16]\r
113 %macro TRANSPOSE6x8_MEM 9\r
114     movq  m0, %1\r
115     movq  m1, %2\r
116     movq  m2, %3\r
117     movq  m3, %4\r
118     movq  m4, %5\r
119     movq  m5, %6\r
120     movq  m6, %7\r
121     SBUTTERFLY bw, m0, m1, m7\r
122     SBUTTERFLY bw, m2, m3, m1\r
123     SBUTTERFLY bw, m4, m5, m3\r
124     movq  [%9+0x10], m1\r
125     SBUTTERFLY bw, m6, %8, m5\r
126     SBUTTERFLY wd, m0, m2, m1\r
127     SBUTTERFLY wd, m4, m6, m2\r
128     punpckhdq m0, m4\r
129     movq  [%9+0x00], m0\r
130     SBUTTERFLY wd, m7, [%9+0x10], m6\r
131     SBUTTERFLY wd, m3, m5, m4\r
132     SBUTTERFLY dq, m7, m3, m0\r
133     SBUTTERFLY dq, m1, m2, m5\r
134     punpckldq m6, m4\r
135     movq  [%9+0x10], m1\r
136     movq  [%9+0x20], m5\r
137     movq  [%9+0x30], m7\r
138     movq  [%9+0x40], m0\r
139     movq  [%9+0x50], m6\r
140 %endmacro\r
141 \r
142 ; in: 8 rows of 8 in %1..%8\r
143 ; out: 8 rows of 8 in %9..%16\r
144 %macro TRANSPOSE8x8_MEM 16\r
145     movq  m0, %1\r
146     movq  m1, %2\r
147     movq  m2, %3\r
148     movq  m3, %4\r
149     movq  m4, %5\r
150     movq  m5, %6\r
151     movq  m6, %7\r
152     SBUTTERFLY bw, m0, m1, m7\r
153     SBUTTERFLY bw, m2, m3, m1\r
154     SBUTTERFLY bw, m4, m5, m3\r
155     SBUTTERFLY bw, m6, %8, m5\r
156     movq  %9,  m3\r
157     SBUTTERFLY wd, m0, m2, m3\r
158     SBUTTERFLY wd, m4, m6, m2\r
159     SBUTTERFLY wd, m7, m1, m6\r
160     movq  %11, m2\r
161     movq  m2,  %9\r
162     SBUTTERFLY wd, m2, m5, m1\r
163     SBUTTERFLY dq, m0, m4, m5\r
164     SBUTTERFLY dq, m7, m2, m4\r
165     movq  %9,  m0\r
166     movq  %10, m5\r
167     movq  %13, m7\r
168     movq  %14, m4\r
169     SBUTTERFLY dq, m3, %11, m0\r
170     SBUTTERFLY dq, m6, m1, m5\r
171     movq  %11, m3\r
172     movq  %12, m0\r
173     movq  %15, m6\r
174     movq  %16, m5\r
175 %endmacro\r
176 \r
177 ; out: %4 = |%1-%2|>%3\r
178 ; clobbers: %5\r
179 %macro DIFF_GT 5\r
180     mova    %5, %2\r
181     mova    %4, %1\r
182     psubusb %5, %1\r
183     psubusb %4, %2\r
184     por     %4, %5\r
185     psubusb %4, %3\r
186 %endmacro\r
187 \r
188 ; out: %4 = |%1-%2|>%3\r
189 ; clobbers: %5\r
190 %macro DIFF_GT2 5\r
191     mova    %5, %2\r
192     mova    %4, %1\r
193     psubusb %5, %1\r
194     psubusb %4, %2\r
195     psubusb %5, %3\r
196     psubusb %4, %3\r
197     pcmpeqb %4, %5\r
198 %endmacro\r
199 \r
200 %macro SPLATW 1\r
201 %ifidn m0, xmm0\r
202     pshuflw  %1, %1, 0\r
203     punpcklqdq %1, %1\r
204 %else\r
205     pshufw   %1, %1, 0\r
206 %endif\r
207 %endmacro\r
208 \r
209 ; in: m0=p1 m1=p0 m2=q0 m3=q1 %1=alpha-1 %2=beta-1\r
210 ; out: m5=beta-1, m7=mask, %3=alpha-1\r
211 ; clobbers: m4,m6\r
212 %macro LOAD_MASK 2-3\r
213     movd     m4, %1\r
214     movd     m5, %2\r
215     SPLATW   m4\r
216     SPLATW   m5\r
217     packuswb m4, m4  ; 16x alpha-1\r
218     packuswb m5, m5  ; 16x beta-1\r
219 %if %0>2\r
220     mova     %3, m4\r
221 %endif\r
222     DIFF_GT  m1, m2, m4, m7, m6 ; |p0-q0| > alpha-1\r
223     DIFF_GT  m0, m1, m5, m4, m6 ; |p1-p0| > beta-1\r
224     por      m7, m4\r
225     DIFF_GT  m3, m2, m5, m4, m6 ; |q1-q0| > beta-1\r
226     por      m7, m4\r
227     pxor     m6, m6\r
228     pcmpeqb  m7, m6\r
229 %endmacro\r
230 \r
231 ; in: m0=p1 m1=p0 m2=q0 m3=q1 m7=(tc&mask)\r
232 ; out: m1=p0' m2=q0'\r
233 ; clobbers: m0,3-6\r
234 %macro DEBLOCK_P0_Q0 0\r
235     mova    m5, m1\r
236     pxor    m5, m2           ; p0^q0\r
237     pand    m5, [pb_01 GLOBAL] ; (p0^q0)&1\r
238     pcmpeqb m4, m4\r
239     pxor    m3, m4\r
240     pavgb   m3, m0           ; (p1 - q1 + 256)>>1\r
241     pavgb   m3, [pb_03 GLOBAL] ; (((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2\r
242     pxor    m4, m1\r
243     pavgb   m4, m2           ; (q0 - p0 + 256)>>1\r
244     pavgb   m3, m5\r
245     paddusb m3, m4           ; d+128+33\r
246     mova    m6, [pb_a1 GLOBAL]\r
247     psubusb m6, m3\r
248     psubusb m3, [pb_a1 GLOBAL]\r
249     pminub  m6, m7\r
250     pminub  m3, m7\r
251     psubusb m1, m6\r
252     psubusb m2, m3\r
253     paddusb m1, m3\r
254     paddusb m2, m6\r
255 %endmacro\r
256 \r
257 ; in: m1=p0 m2=q0\r
258 ;     %1=p1 %2=q2 %3=[q2] %4=[q1] %5=tc0 %6=tmp\r
259 ; out: [q1] = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 )\r
260 ; clobbers: q2, tmp, tc0\r
261 %macro LUMA_Q1 6\r
262     mova    %6, m1\r
263     pavgb   %6, m2\r
264     pavgb   %2, %6             ; avg(p2,avg(p0,q0))\r
265     pxor    %6, %3\r
266     pand    %6, [pb_01 GLOBAL] ; (p2^avg(p0,q0))&1\r
267     psubusb %2, %6             ; (p2+((p0+q0+1)>>1))>>1\r
268     mova    %6, %1\r
269     psubusb %6, %5\r
270     paddusb %5, %1\r
271     pmaxub  %2, %6\r
272     pminub  %2, %5\r
273     mova    %4, %2\r
274 %endmacro\r
275 \r
276 %ifdef ARCH_X86_64\r
277 ;-----------------------------------------------------------------------------\r
278 ; void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )\r
279 ;-----------------------------------------------------------------------------\r
280 INIT_XMM\r
281 cglobal x264_deblock_v_luma_sse2\r
282     movd    m8, [r4] ; tc0\r
283     lea     r4, [r1*3]\r
284     dec     r2d        ; alpha-1\r
285     neg     r4\r
286     dec     r3d        ; beta-1\r
287     add     r4, r0     ; pix-3*stride\r
288 \r
289     mova    m0, [r4+r1]   ; p1\r
290     mova    m1, [r4+2*r1] ; p0\r
291     mova    m2, [r0]      ; q0\r
292     mova    m3, [r0+r1]   ; q1\r
293     LOAD_MASK r2d, r3d\r
294 \r
295     punpcklbw m8, m8\r
296     punpcklbw m8, m8 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]\r
297     pcmpeqb m9, m9\r
298     pcmpeqb m9, m8\r
299     pandn   m9, m7\r
300     pand    m8, m9\r
301 \r
302     movdqa  m3, [r4] ; p2\r
303     DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1\r
304     pand    m6, m9\r
305     mova    m7, m8\r
306     psubb   m7, m6\r
307     pand    m6, m8\r
308     LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4\r
309 \r
310     movdqa  m4, [r0+2*r1] ; q2\r
311     DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1\r
312     pand    m6, m9\r
313     pand    m8, m6\r
314     psubb   m7, m6\r
315     mova    m3, [r0+r1]\r
316     LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m8, m6\r
317 \r
318     DEBLOCK_P0_Q0\r
319     mova    [r4+2*r1], m1\r
320     mova    [r0], m2\r
321     ret\r
322 \r
323 ;-----------------------------------------------------------------------------\r
324 ; void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )\r
325 ;-----------------------------------------------------------------------------\r
326 INIT_MMX\r
327 cglobal x264_deblock_h_luma_sse2\r
328     movsxd r10, esi\r
329     lea    r11, [r10+r10*2]\r
330     lea    rax, [r0-4]\r
331     lea    r9,  [r0-4+r11]\r
332     sub    rsp, 0x68\r
333     %define pix_tmp rsp\r
334 \r
335     ; transpose 6x16 -> tmp space\r
336     TRANSPOSE6x8_MEM  PASS8ROWS(rax, r9, r10, r11), pix_tmp\r
337     lea    rax, [rax+r10*8]\r
338     lea    r9,  [r9 +r10*8]\r
339     TRANSPOSE6x8_MEM  PASS8ROWS(rax, r9, r10, r11), pix_tmp+8\r
340 \r
341     ; vertical filter\r
342     ; alpha, beta, tc0 are still in r2d, r3d, r4\r
343     ; don't backup rax, r9, r10, r11 because x264_deblock_v_luma_sse2 doesn't use them\r
344     lea    r0, [pix_tmp+0x30]\r
345     mov    esi, 0x10\r
346     call   x264_deblock_v_luma_sse2\r
347 \r
348     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)\r
349     add    rax, 2\r
350     add    r9,  2\r
351     movq   m0, [pix_tmp+0x18]\r
352     movq   m1, [pix_tmp+0x28]\r
353     movq   m2, [pix_tmp+0x38]\r
354     movq   m3, [pix_tmp+0x48]\r
355     TRANSPOSE8x4_STORE  PASS8ROWS(rax, r9, r10, r11)\r
356 \r
357     shl    r10, 3\r
358     sub    rax, r10\r
359     sub    r9,  r10\r
360     shr    r10, 3\r
361     movq   m0, [pix_tmp+0x10]\r
362     movq   m1, [pix_tmp+0x20]\r
363     movq   m2, [pix_tmp+0x30]\r
364     movq   m3, [pix_tmp+0x40]\r
365     TRANSPOSE8x4_STORE  PASS8ROWS(rax, r9, r10, r11)\r
366 \r
367     add    rsp, 0x68\r
368     ret\r
369 \r
370 %else\r
371 \r
372 %macro DEBLOCK_LUMA 3\r
373 ;-----------------------------------------------------------------------------\r
374 ; void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )\r
375 ;-----------------------------------------------------------------------------\r
376 cglobal x264_deblock_%2_luma_%1, 5,5\r
377     lea     r4, [r1*3]\r
378     dec     r2     ; alpha-1\r
379     neg     r4\r
380     dec     r3     ; beta-1\r
381     add     r4, r0 ; pix-3*stride\r
382     %assign pad 2*%3+12-(stack_offset&15)\r
383     SUB     esp, pad\r
384 \r
385     mova    m0, [r4+r1]   ; p1\r
386     mova    m1, [r4+2*r1] ; p0\r
387     mova    m2, [r0]      ; q0\r
388     mova    m3, [r0+r1]   ; q1\r
389     LOAD_MASK r2, r3\r
390 \r
391     mov     r3, r4m\r
392     movd    m4, [r3] ; tc0\r
393     punpcklbw m4, m4\r
394     punpcklbw m4, m4 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]\r
395     mova   [esp+%3], m4 ; tc\r
396     pcmpeqb m3, m3\r
397     pcmpgtb m4, m3\r
398     pand    m4, m7\r
399     mova   [esp], m4 ; mask\r
400 \r
401     mova    m3, [r4] ; p2\r
402     DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1\r
403     pand    m6, m4\r
404     pand    m4, [esp+%3] ; tc\r
405     mova    m7, m4\r
406     psubb   m7, m6\r
407     pand    m6, m4\r
408     LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4\r
409 \r
410     mova    m4, [r0+2*r1] ; q2\r
411     DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1\r
412     mova    m5, [esp] ; mask\r
413     pand    m6, m5\r
414     mova    m5, [esp+%3] ; tc\r
415     pand    m5, m6\r
416     psubb   m7, m6\r
417     mova    m3, [r0+r1]\r
418     LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m5, m6\r
419 \r
420     DEBLOCK_P0_Q0\r
421     mova    [r4+2*r1], m1\r
422     mova    [r0], m2\r
423     ADD     esp, pad\r
424     RET\r
425 \r
426 ;-----------------------------------------------------------------------------\r
427 ; void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )\r
428 ;-----------------------------------------------------------------------------\r
429 INIT_MMX\r
430 cglobal x264_deblock_h_luma_%1, 0,5\r
431     mov    r0, r0m\r
432     mov    r3, r1m\r
433     lea    r4, [r3*3]\r
434     sub    r0, 4\r
435     lea    r1, [r0+r4]\r
436     %assign pad 0x78-(stack_offset&15)\r
437     SUB    esp, pad\r
438 %define pix_tmp esp+12\r
439 \r
440     ; transpose 6x16 -> tmp space\r
441     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp\r
442     lea    r0, [r0+r3*8]\r
443     lea    r1, [r1+r3*8]\r
444     TRANSPOSE6x8_MEM  PASS8ROWS(r0, r1, r3, r4), pix_tmp+8\r
445 \r
446     ; vertical filter\r
447     lea    r0, [pix_tmp+0x30]\r
448     PUSH   dword r4m\r
449     PUSH   dword r3m\r
450     PUSH   dword r2m\r
451     PUSH   dword 16\r
452     PUSH   dword r0\r
453     call   x264_deblock_%2_luma_%1\r
454 %ifidn %2, v8\r
455     add    dword [esp   ], 8 ; pix_tmp+0x38\r
456     add    dword [esp+16], 2 ; tc0+2\r
457     call   x264_deblock_%2_luma_%1\r
458 %endif\r
459     ADD    esp, 20\r
460 \r
461     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)\r
462     mov    r0, r0m\r
463     sub    r0, 2\r
464     lea    r1, [r0+r4]\r
465 \r
466     movq   m0, [pix_tmp+0x10]\r
467     movq   m1, [pix_tmp+0x20]\r
468     movq   m2, [pix_tmp+0x30]\r
469     movq   m3, [pix_tmp+0x40]\r
470     TRANSPOSE8x4_STORE  PASS8ROWS(r0, r1, r3, r4)\r
471 \r
472     lea    r0, [r0+r3*8]\r
473     lea    r1, [r1+r3*8]\r
474     movq   m0, [pix_tmp+0x18]\r
475     movq   m1, [pix_tmp+0x28]\r
476     movq   m2, [pix_tmp+0x38]\r
477     movq   m3, [pix_tmp+0x48]\r
478     TRANSPOSE8x4_STORE  PASS8ROWS(r0, r1, r3, r4)\r
479 \r
480     ADD    esp, pad\r
481     RET\r
482 %endmacro ; DEBLOCK_LUMA\r
483 \r
484 INIT_XMM\r
485 DEBLOCK_LUMA sse2, v, 16\r
486 \r
487 %endif ; ARCH\r
488 \r
489 \r
490 \r
491 %macro LUMA_INTRA_P012 4 ; p0..p3 in memory\r
492     mova  t0, p2\r
493     mova  t1, p0\r
494     pavgb t0, p1\r
495     pavgb t1, q0\r
496     pavgb t0, t1 ; ((p2+p1+1)/2 + (p0+q0+1)/2 + 1)/2\r
497     mova  t5, t1\r
498     mova  t2, p2\r
499     mova  t3, p0\r
500     paddb t2, p1\r
501     paddb t3, q0\r
502     paddb t2, t3\r
503     mova  t3, t2\r
504     mova  t4, t2\r
505     psrlw t2, 1\r
506     pavgb t2, mpb_00\r
507     pxor  t2, t0\r
508     pand  t2, mpb_01\r
509     psubb t0, t2 ; p1' = (p2+p1+p0+q0+2)/4;\r
510 \r
511     mova  t1, p2\r
512     mova  t2, p2\r
513     pavgb t1, q1\r
514     psubb t2, q1\r
515     paddb t3, t3\r
516     psubb t3, t2 ; p2+2*p1+2*p0+2*q0+q1\r
517     pand  t2, mpb_01\r
518     psubb t1, t2\r
519     pavgb t1, p1\r
520     pavgb t1, t5 ; (((p2+q1)/2 + p1+1)/2 + (p0+q0+1)/2 + 1)/2\r
521     psrlw t3, 2\r
522     pavgb t3, mpb_00\r
523     pxor  t3, t1\r
524     pand  t3, mpb_01\r
525     psubb t1, t3 ; p0'a = (p2+2*p1+2*p0+2*q0+q1+4)/8\r
526 \r
527     mova  t3, p0\r
528     mova  t2, p0\r
529     pxor  t3, q1\r
530     pavgb t2, q1\r
531     pand  t3, mpb_01\r
532     psubb t2, t3\r
533     pavgb t2, p1 ; p0'b = (2*p1+p0+q0+2)/4\r
534 \r
535     pxor  t1, t2\r
536     pxor  t2, p0\r
537     pand  t1, mask1p\r
538     pand  t2, mask0\r
539     pxor  t1, t2\r
540     pxor  t1, p0\r
541     mova  %1, t1 ; store p0\r
542 \r
543     mova  t1, %4 ; p3\r
544     mova  t2, t1\r
545     pavgb t1, p2\r
546     paddb t2, p2\r
547     pavgb t1, t0 ; (p3+p2+1)/2 + (p2+p1+p0+q0+2)/4\r
548     paddb t2, t2\r
549     paddb t2, t4 ; 2*p3+3*p2+p1+p0+q0\r
550     psrlw t2, 2\r
551     pavgb t2, mpb_00\r
552     pxor  t2, t1\r
553     pand  t2, mpb_01\r
554     psubb t1, t2 ; p2' = (2*p3+3*p2+p1+p0+q0+4)/8\r
555 \r
556     pxor  t0, p1\r
557     pxor  t1, p2\r
558     pand  t0, mask1p\r
559     pand  t1, mask1p\r
560     pxor  t0, p1\r
561     pxor  t1, p2\r
562     mova  %2, t0 ; store p1\r
563     mova  %3, t1 ; store p2\r
564 %endmacro\r
565 \r
566 %macro LUMA_INTRA_SWAP_PQ 0\r
567     %define q1 m0\r
568     %define q0 m1\r
569     %define p0 m2\r
570     %define p1 m3\r
571     %define p2 q2\r
572     %define mask1p mask1q\r
573 %endmacro\r
574 \r
575 %macro DEBLOCK_LUMA_INTRA 2\r
576     %define p1 m0\r
577     %define p0 m1\r
578     %define q0 m2\r
579     %define q1 m3\r
580     %define t0 m4\r
581     %define t1 m5\r
582     %define t2 m6\r
583     %define t3 m7\r
584 %ifdef ARCH_X86_64\r
585     %define p2 m8\r
586     %define q2 m9\r
587     %define t4 m10\r
588     %define t5 m11\r
589     %define mask0 m12\r
590     %define mask1p m13\r
591     %define mask1q [rsp-24]\r
592     %define mpb_00 m14\r
593     %define mpb_01 m15\r
594 %else\r
595     %define spill(x) [esp+16*x+((stack_offset+4)&15)]\r
596     %define p2 [r4+r1]\r
597     %define q2 [r0+2*r1]\r
598     %define t4 spill(0)\r
599     %define t5 spill(1)\r
600     %define mask0 spill(2)\r
601     %define mask1p spill(3)\r
602     %define mask1q spill(4)\r
603     %define mpb_00 [pb_00 GLOBAL]\r
604     %define mpb_01 [pb_01 GLOBAL]\r
605 %endif\r
606 \r
607 ;-----------------------------------------------------------------------------\r
608 ; void x264_deblock_v_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta )\r
609 ;-----------------------------------------------------------------------------\r
610 cglobal x264_deblock_%2_luma_intra_%1, 4,6\r
611 %ifndef ARCH_X86_64\r
612     sub     esp, 0x60\r
613 %endif\r
614     lea     r4, [r1*4]\r
615     lea     r5, [r1*3] ; 3*stride\r
616     dec     r2d        ; alpha-1\r
617     jl .end\r
618     neg     r4\r
619     dec     r3d        ; beta-1\r
620     jl .end\r
621     add     r4, r0     ; pix-4*stride\r
622     mova    p1, [r4+2*r1]\r
623     mova    p0, [r4+r5]\r
624     mova    q0, [r0]\r
625     mova    q1, [r0+r1]\r
626 %ifdef ARCH_X86_64\r
627     pxor    mpb_00, mpb_00\r
628     mova    mpb_01, [pb_01 GLOBAL]\r
629     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0\r
630     SWAP    7, 12 ; m12=mask0\r
631     pavgb   t5, mpb_00\r
632     pavgb   t5, mpb_01 ; alpha/4+1\r
633     movdqa  p2, [r4+r1]\r
634     movdqa  q2, [r0+2*r1]\r
635     DIFF_GT2 p0, q0, t5, t0, t3 ; t0 = |p0-q0| > alpha/4+1\r
636     DIFF_GT2 p0, p2, m5, t2, t5 ; mask1 = |p2-p0| > beta-1\r
637     DIFF_GT2 q0, q2, m5, t4, t5 ; t4 = |q2-q0| > beta-1\r
638     pand    t0, mask0\r
639     pand    t4, t0\r
640     pand    t2, t0\r
641     mova    mask1q, t4\r
642     mova    mask1p, t2\r
643 %else\r
644     LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0\r
645     mova    m4, t5\r
646     mova    mask0, m7\r
647     pavgb   m4, [pb_00 GLOBAL]\r
648     pavgb   m4, [pb_01 GLOBAL] ; alpha/4+1\r
649     DIFF_GT2 p0, q0, m4, m6, m7 ; m6 = |p0-q0| > alpha/4+1\r
650     pand    m6, mask0\r
651     DIFF_GT2 p0, p2, m5, m4, m7 ; m4 = |p2-p0| > beta-1\r
652     pand    m4, m6\r
653     mova    mask1p, m4\r
654     DIFF_GT2 q0, q2, m5, m4, m7 ; m4 = |q2-q0| > beta-1\r
655     pand    m4, m6\r
656     mova    mask1q, m4\r
657 %endif\r
658     LUMA_INTRA_P012 [r4+r5], [r4+2*r1], [r4+r1], [r4]\r
659     LUMA_INTRA_SWAP_PQ\r
660     LUMA_INTRA_P012 [r0], [r0+r1], [r0+2*r1], [r0+r5]\r
661 .end:\r
662 %ifndef ARCH_X86_64\r
663     add     esp, 0x60\r
664 %endif\r
665     RET\r
666 \r
667 INIT_MMX\r
668 %ifdef ARCH_X86_64\r
669 ;-----------------------------------------------------------------------------\r
670 ; void x264_deblock_h_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta )\r
671 ;-----------------------------------------------------------------------------\r
672 cglobal x264_deblock_h_luma_intra_%1\r
673     movsxd r10, r1d\r
674     lea    r11, [r10*3]\r
675     lea    rax, [r0-4]\r
676     lea    r9,  [r0-4+r11]\r
677     sub    rsp, 0x88\r
678     %define pix_tmp rsp\r
679 \r
680     ; transpose 8x16 -> tmp space\r
681     TRANSPOSE8x8_MEM  PASS8ROWS(rax, r9, r10, r11), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)\r
682     lea    rax, [rax+r10*8]\r
683     lea    r9,  [r9+r10*8]\r
684     TRANSPOSE8x8_MEM  PASS8ROWS(rax, r9, r10, r11), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)\r
685 \r
686     lea    r0,  [pix_tmp+0x40]\r
687     mov    r1,  0x10\r
688     call   x264_deblock_v_luma_intra_%1\r
689 \r
690     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)\r
691     lea    r9, [rax+r11]\r
692     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(rax, r9, r10, r11)\r
693     shl    r10, 3\r
694     sub    rax, r10\r
695     sub    r9,  r10\r
696     shr    r10, 3\r
697     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(rax, r9, r10, r11)\r
698     add    rsp, 0x88\r
699     ret\r
700 %else\r
701 cglobal x264_deblock_h_luma_intra_%1, 2,4\r
702     lea    r3,  [r1*3]\r
703     sub    r0,  4\r
704     lea    r2,  [r0+r3]\r
705 %assign pad 0x8c-(stack_offset&15)\r
706     SUB    rsp, pad\r
707     %define pix_tmp rsp\r
708 \r
709     ; transpose 8x16 -> tmp space\r
710     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)\r
711     lea    r0,  [r0+r1*8]\r
712     lea    r2,  [r2+r1*8]\r
713     TRANSPOSE8x8_MEM  PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)\r
714 \r
715     lea    r0,  [pix_tmp+0x40]\r
716     PUSH   dword r3m\r
717     PUSH   dword r2m\r
718     PUSH   dword 16\r
719     PUSH   r0\r
720     call   x264_deblock_%2_luma_intra_%1\r
721 %ifidn %2, v8\r
722     add    dword [rsp], 8 ; pix_tmp+8\r
723     call   x264_deblock_%2_luma_intra_%1\r
724 %endif\r
725     ADD    esp, 16\r
726 \r
727     mov    r1,  r1m\r
728     mov    r0,  r0m\r
729     lea    r3,  [r1*3]\r
730     sub    r0,  4\r
731     lea    r2,  [r0+r3]\r
732     ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)\r
733     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)\r
734     lea    r0,  [r0+r1*8]\r
735     lea    r2,  [r2+r1*8]\r
736     TRANSPOSE8x8_MEM  PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)\r
737     ADD    rsp, pad\r
738     RET\r
739 %endif ; ARCH_X86_64\r
740 %endmacro ; DEBLOCK_LUMA_INTRA\r
741 \r
742 INIT_XMM\r
743 DEBLOCK_LUMA_INTRA sse2, v\r
744 %ifndef ARCH_X86_64\r
745 INIT_MMX\r
746 DEBLOCK_LUMA_INTRA mmxext, v8\r
747 %endif\r