]> git.sesse.net Git - x264/blob - common/x86/dct-a.asm
Deduplicate asm constants, automate name prefixing
[x264] / common / x86 / dct-a.asm
1 ;*****************************************************************************
2 ;* dct-a.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2003-2008 x264 project
5 ;*
6 ;* Authors: Holger Lubitz <holger@lubitz.org>
7 ;*          Loren Merritt <lorenm@u.washington.edu>
8 ;*          Laurent Aimar <fenrir@via.ecp.fr>
9 ;*          Min Chen <chenm001.163.com>
10 ;*
11 ;* This program is free software; you can redistribute it and/or modify
12 ;* it under the terms of the GNU General Public License as published by
13 ;* the Free Software Foundation; either version 2 of the License, or
14 ;* (at your option) any later version.
15 ;*
16 ;* This program is distributed in the hope that it will be useful,
17 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;* GNU General Public License for more details.
20 ;*
21 ;* You should have received a copy of the GNU General Public License
22 ;* along with this program; if not, write to the Free Software
23 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24 ;*****************************************************************************
25
26 %include "x86inc.asm"
27 %include "x86util.asm"
28
29 %macro SHUFFLE_16BIT 8
30     %rep 8
31         db %1*2
32         db %1*2+1
33         %rotate 1
34     %endrep
35 %endmacro
36
37 SECTION_RODATA
38 pb_sub4frame:   db 0,1,4,8,5,2,3,6,9,12,13,10,7,11,14,15
39 pb_sub4field:   db 0,4,1,8,12,5,9,13,2,6,10,14,3,7,11,15
40 pb_subacmask:   dw 0,-1,-1,-1,-1,-1,-1,-1
41 pb_scan4framea: SHUFFLE_16BIT 6,3,7,0,4,1,2,5
42 pb_scan4frameb: SHUFFLE_16BIT 0,4,1,2,5,6,3,7
43 pb_idctdc_unpack: db 0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3
44 pb_idctdc_unpack2: db 4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7
45
46 SECTION .text
47
48 cextern pw_32_0
49 cextern pw_32
50 cextern pw_8000
51 cextern hsub_mul
52 cextern pb_1
53 cextern pw_1
54
55 %macro WALSH4_1D 5
56     SUMSUB_BADC m%4, m%3, m%2, m%1, m%5
57     SUMSUB_BADC m%4, m%2, m%3, m%1, m%5
58     SWAP %1, %4, %3
59 %endmacro
60
61 %macro SUMSUB_17BIT 4 ; a, b, tmp, 0x8000
62     movq  m%3, m%4
63     pxor  m%1, m%4
64     psubw m%3, m%2
65     pxor  m%2, m%4
66     pavgw m%3, m%1
67     pavgw m%2, m%1
68     pxor  m%3, m%4
69     pxor  m%2, m%4
70     SWAP %1, %2, %3
71 %endmacro
72
73 INIT_MMX
74 ;-----------------------------------------------------------------------------
75 ; void dct4x4dc( int16_t d[4][4] )
76 ;-----------------------------------------------------------------------------
77 cglobal dct4x4dc_mmx, 1,1
78     movq   m3, [r0+24]
79     movq   m2, [r0+16]
80     movq   m1, [r0+ 8]
81     movq   m0, [r0+ 0]
82     movq   m7, [pw_8000] ; convert to unsigned and back, so that pavgw works
83     WALSH4_1D  0,1,2,3,4
84     TRANSPOSE4x4W 0,1,2,3,4
85     SUMSUB_BADC m1, m0, m3, m2, m4
86     SWAP 0, 1
87     SWAP 2, 3
88     SUMSUB_17BIT 0,2,4,7
89     SUMSUB_17BIT 1,3,5,7
90     movq  [r0+0], m0
91     movq  [r0+8], m2
92     movq [r0+16], m3
93     movq [r0+24], m1
94     RET
95
96 ;-----------------------------------------------------------------------------
97 ; void idct4x4dc( int16_t d[4][4] )
98 ;-----------------------------------------------------------------------------
99 cglobal idct4x4dc_mmx, 1,1
100     movq   m3, [r0+24]
101     movq   m2, [r0+16]
102     movq   m1, [r0+ 8]
103     movq   m0, [r0+ 0]
104     WALSH4_1D  0,1,2,3,4
105     TRANSPOSE4x4W 0,1,2,3,4
106     WALSH4_1D  0,1,2,3,4
107     movq  [r0+ 0], m0
108     movq  [r0+ 8], m1
109     movq  [r0+16], m2
110     movq  [r0+24], m3
111     RET
112
113 %macro SUB_DCT4 1
114 ;-----------------------------------------------------------------------------
115 ; void sub4x4_dct( int16_t dct[4][4], uint8_t *pix1, uint8_t *pix2 )
116 ;-----------------------------------------------------------------------------
117 cglobal sub4x4_dct_%1, 3,3
118 %ifidn %1, mmx
119 .skip_prologue:
120     LOAD_DIFF  m0, m4, m5, [r1+0*FENC_STRIDE], [r2+0*FDEC_STRIDE]
121     LOAD_DIFF  m3, m4, m5, [r1+3*FENC_STRIDE], [r2+3*FDEC_STRIDE]
122     LOAD_DIFF  m1, m4, m5, [r1+1*FENC_STRIDE], [r2+1*FDEC_STRIDE]
123     LOAD_DIFF  m2, m4, m5, [r1+2*FENC_STRIDE], [r2+2*FDEC_STRIDE]
124 %else
125     mova m5, [hsub_mul]
126     LOAD_DIFF8x4_SSSE3 0, 3, 1, 2, 4, 5, r1, r2
127 %endif
128     DCT4_1D 0,1,2,3,4
129     TRANSPOSE4x4W 0,1,2,3,4
130     DCT4_1D 0,1,2,3,4
131     movq  [r0+ 0], m0
132     movq  [r0+ 8], m1
133     movq  [r0+16], m2
134     movq  [r0+24], m3
135     RET
136 %endmacro
137
138 SUB_DCT4 mmx
139 SUB_DCT4 ssse3
140
141 ;-----------------------------------------------------------------------------
142 ; void add4x4_idct( uint8_t *p_dst, int16_t dct[4][4] )
143 ;-----------------------------------------------------------------------------
144 cglobal add4x4_idct_mmx, 2,2
145     pxor m7, m7
146 .skip_prologue:
147     movq  m1, [r1+ 8]
148     movq  m3, [r1+24]
149     movq  m2, [r1+16]
150     movq  m0, [r1+ 0]
151     IDCT4_1D 0,1,2,3,4,5
152     TRANSPOSE4x4W 0,1,2,3,4
153     paddw m0, [pw_32]
154     IDCT4_1D 0,1,2,3,4,5
155     STORE_DIFF  m0, m4, m7, [r0+0*FDEC_STRIDE]
156     STORE_DIFF  m1, m4, m7, [r0+1*FDEC_STRIDE]
157     STORE_DIFF  m2, m4, m7, [r0+2*FDEC_STRIDE]
158     STORE_DIFF  m3, m4, m7, [r0+3*FDEC_STRIDE]
159     RET
160
161 INIT_XMM
162 cglobal add4x4_idct_sse4, 2,2,6
163     mova      m0, [r1+0x00]     ; row1/row0
164     mova      m2, [r1+0x10]     ; row3/row2
165     mova      m1, m0            ; row1/row0
166     psraw     m0, 1             ; row1>>1/...
167     mova      m3, m2            ; row3/row2
168     psraw     m2, 1             ; row3>>1/...
169     movsd     m0, m1            ; row1>>1/row0
170     movsd     m2, m3            ; row3>>1/row2
171     psubw     m0, m3            ; row1>>1-row3/row0-2
172     paddw     m2, m1            ; row3>>1+row1/row0+2
173     SBUTTERFLY2 wd, 0, 2, 1
174     SUMSUB_BA m2, m0, m1
175     pshuflw   m1, m2, 10110001b
176     pshufhw   m2, m2, 10110001b
177     punpckldq m1, m0
178     punpckhdq m2, m0
179     SWAP 0, 1
180
181     mova      m1, [pw_32_0]
182     paddw     m1, m0            ; row1/row0 corrected
183     psraw     m0, 1             ; row1>>1/...
184     mova      m3, m2            ; row3/row2
185     psraw     m2, 1             ; row3>>1/...
186     movsd     m0, m1            ; row1>>1/row0
187     movsd     m2, m3            ; row3>>1/row2
188     psubw     m0, m3            ; row1>>1-row3/row0-2
189     paddw     m2, m1            ; row3>>1+row1/row0+2
190     SBUTTERFLY2 qdq, 0, 2, 1
191     SUMSUB_BA m2, m0, m1
192
193     movd      m4, [r0+FDEC_STRIDE*0]
194     movd      m1, [r0+FDEC_STRIDE*1]
195     movd      m3, [r0+FDEC_STRIDE*2]
196     movd      m5, [r0+FDEC_STRIDE*3]
197     punpckldq m1, m4            ; row0/row1
198     pxor      m4, m4
199     punpckldq m3, m5            ; row3/row2
200     punpcklbw m1, m4
201     psraw     m2, 6
202     punpcklbw m3, m4
203     psraw     m0, 6
204     paddsw    m2, m1
205     paddsw    m0, m3
206     packuswb  m0, m2            ; row0/row1/row3/row2
207     pextrd   [r0+FDEC_STRIDE*0], m0, 3
208     pextrd   [r0+FDEC_STRIDE*1], m0, 2
209     movd     [r0+FDEC_STRIDE*2], m0
210     pextrd   [r0+FDEC_STRIDE*3], m0, 1
211     RET
212
213 INIT_MMX
214 ;-----------------------------------------------------------------------------
215 ; void sub8x8_dct( int16_t dct[4][4][4], uint8_t *pix1, uint8_t *pix2 )
216 ;-----------------------------------------------------------------------------
217 %macro SUB_NxN_DCT 6
218 cglobal %1, 3,3,11
219 %if mmsize == 8
220     pxor m7, m7
221 %else
222     add r2, 4*FDEC_STRIDE
223     mova m7, [hsub_mul]
224 %endif
225 .skip_prologue:
226 %ifdef WIN64
227     sub  rsp, 8
228 %endif
229     call %2
230     add  r0, %3
231     add  r1, %4-%5-%6*FENC_STRIDE
232     add  r2, %4-%5-%6*FDEC_STRIDE
233     call %2
234     add  r0, %3
235     add  r1, (%4-%6)*FENC_STRIDE-%5-%4
236     add  r2, (%4-%6)*FDEC_STRIDE-%5-%4
237     call %2
238     add  r0, %3
239     add  r1, %4-%5-%6*FENC_STRIDE
240     add  r2, %4-%5-%6*FDEC_STRIDE
241 %ifdef WIN64
242     add  rsp, 8
243     call %2
244     RET
245 %else
246     jmp  %2
247 %endif
248 %endmacro
249
250 ;-----------------------------------------------------------------------------
251 ; void add8x8_idct( uint8_t *pix, int16_t dct[4][4][4] )
252 ;-----------------------------------------------------------------------------
253 %macro ADD_NxN_IDCT 6-7
254 cglobal %1, 2,2,11
255     pxor m7, m7
256 %if mmsize==16
257     add  r0, 4*FDEC_STRIDE
258 %endif
259 .skip_prologue:
260 %ifdef WIN64
261     sub  rsp, 8
262 %endif
263     call %2
264     add  r0, %4-%5-%6*FDEC_STRIDE
265     add  r1, %3
266     call %2
267     add  r0, (%4-%6)*FDEC_STRIDE-%5-%4
268     add  r1, %3
269     call %2
270     add  r0, %4-%5-%6*FDEC_STRIDE
271     add  r1, %3
272 %ifdef WIN64
273     add  rsp, 8
274     call %2
275     RET
276 %else
277     jmp  %2
278 %endif
279 %endmacro
280
281 %ifndef ARCH_X86_64
282 SUB_NxN_DCT  sub8x8_dct_mmx,    sub4x4_dct_mmx.skip_prologue,  32, 4, 0, 0
283 ADD_NxN_IDCT add8x8_idct_mmx,   add4x4_idct_mmx.skip_prologue, 32, 4, 0, 0
284 SUB_NxN_DCT  sub16x16_dct_mmx,  sub8x8_dct_mmx.skip_prologue,  32, 8, 4, 4
285 ADD_NxN_IDCT add16x16_idct_mmx, add8x8_idct_mmx.skip_prologue, 32, 8, 4, 4
286
287 cextern sub8x8_dct8_mmx.skip_prologue
288 cextern add8x8_idct8_mmx.skip_prologue
289 SUB_NxN_DCT  sub16x16_dct8_mmx,  sub8x8_dct8_mmx.skip_prologue,  128, 8, 0, 0
290 ADD_NxN_IDCT add16x16_idct8_mmx, add8x8_idct8_mmx.skip_prologue, 128, 8, 0, 0
291 %endif
292
293 INIT_XMM
294
295 cextern sub8x8_dct_sse2.skip_prologue
296 cextern sub8x8_dct_ssse3.skip_prologue
297 SUB_NxN_DCT  sub16x16_dct_sse2,  sub8x8_dct_sse2.skip_prologue,  128, 8, 0, 0
298 SUB_NxN_DCT  sub16x16_dct_ssse3, sub8x8_dct_ssse3.skip_prologue, 128, 8, 0, 0
299 cextern add8x8_idct_sse2.skip_prologue
300 ADD_NxN_IDCT add16x16_idct_sse2, add8x8_idct_sse2.skip_prologue, 2*64, 8, 0, 0
301
302 cextern sub8x8_dct8_sse2.skip_prologue
303 cextern add8x8_idct8_sse2.skip_prologue
304 SUB_NxN_DCT  sub16x16_dct8_sse2,  sub8x8_dct8_sse2.skip_prologue,  128, 8, 0, 0
305 ADD_NxN_IDCT add16x16_idct8_sse2, add8x8_idct8_sse2.skip_prologue, 128, 8, 0, 0
306
307 cextern sub8x8_dct8_ssse3.skip_prologue
308 SUB_NxN_DCT  sub16x16_dct8_ssse3, sub8x8_dct8_ssse3.skip_prologue, 128, 8, 0, 0
309
310
311 ;-----------------------------------------------------------------------------
312 ; void add8x8_idct_dc( uint8_t *p_dst, int16_t *dct2x2 )
313 ;-----------------------------------------------------------------------------
314
315 %macro ADD_DC 3
316     movq      mm4, [%3+FDEC_STRIDE*0]
317     movq      mm5, [%3+FDEC_STRIDE*1]
318     movq      mm6, [%3+FDEC_STRIDE*2]
319     paddusb   mm4, %1
320     paddusb   mm5, %1
321     paddusb   mm6, %1
322     paddusb    %1, [%3+FDEC_STRIDE*3]
323     psubusb   mm4, %2
324     psubusb   mm5, %2
325     psubusb   mm6, %2
326     psubusb    %1, %2
327     movq      [%3+FDEC_STRIDE*0], mm4
328     movq      [%3+FDEC_STRIDE*1], mm5
329     movq      [%3+FDEC_STRIDE*2], mm6
330     movq      [%3+FDEC_STRIDE*3], %1
331 %endmacro
332
333 cglobal add8x8_idct_dc_mmx, 2,2
334     movq      mm0, [r1]
335     pxor      mm1, mm1
336     add        r0, FDEC_STRIDE*4
337     paddw     mm0, [pw_32]
338     psraw     mm0, 6
339     psubw     mm1, mm0
340     packuswb  mm0, mm0
341     packuswb  mm1, mm1
342     punpcklbw mm0, mm0
343     punpcklbw mm1, mm1
344     pshufw    mm2, mm0, 0xFA
345     pshufw    mm3, mm1, 0xFA
346     punpcklbw mm0, mm0
347     punpcklbw mm1, mm1
348     ADD_DC    mm0, mm1, r0-FDEC_STRIDE*4
349     ADD_DC    mm2, mm3, r0
350     RET
351
352 cglobal add8x8_idct_dc_ssse3, 2,2
353     movq      xmm0, [r1]
354     pxor      xmm1, xmm1
355     add         r0, FDEC_STRIDE*4
356     paddw     xmm0, [pw_32]
357     psraw     xmm0, 6
358     psubw     xmm1, xmm0
359     movdqa    xmm5, [pb_idctdc_unpack]
360     packuswb  xmm0, xmm0
361     packuswb  xmm1, xmm1
362     pshufb    xmm0, xmm5
363     pshufb    xmm1, xmm5
364     movq      xmm2, [r0+FDEC_STRIDE*-4]
365     movq      xmm3, [r0+FDEC_STRIDE*-3]
366     movq      xmm4, [r0+FDEC_STRIDE*-2]
367     movq      xmm5, [r0+FDEC_STRIDE*-1]
368     movhps    xmm2, [r0+FDEC_STRIDE* 0]
369     movhps    xmm3, [r0+FDEC_STRIDE* 1]
370     movhps    xmm4, [r0+FDEC_STRIDE* 2]
371     movhps    xmm5, [r0+FDEC_STRIDE* 3]
372     paddusb   xmm2, xmm0
373     paddusb   xmm3, xmm0
374     paddusb   xmm4, xmm0
375     paddusb   xmm5, xmm0
376     psubusb   xmm2, xmm1
377     psubusb   xmm3, xmm1
378     psubusb   xmm4, xmm1
379     psubusb   xmm5, xmm1
380     movq      [r0+FDEC_STRIDE*-4], xmm2
381     movq      [r0+FDEC_STRIDE*-3], xmm3
382     movq      [r0+FDEC_STRIDE*-2], xmm4
383     movq      [r0+FDEC_STRIDE*-1], xmm5
384     movhps    [r0+FDEC_STRIDE* 0], xmm2
385     movhps    [r0+FDEC_STRIDE* 1], xmm3
386     movhps    [r0+FDEC_STRIDE* 2], xmm4
387     movhps    [r0+FDEC_STRIDE* 3], xmm5
388     RET
389
390 cglobal add16x16_idct_dc_mmx, 2,3
391     mov       r2, 4
392 .loop:
393     movq      mm0, [r1]
394     pxor      mm1, mm1
395     paddw     mm0, [pw_32]
396     psraw     mm0, 6
397     psubw     mm1, mm0
398     packuswb  mm0, mm0
399     packuswb  mm1, mm1
400     punpcklbw mm0, mm0
401     punpcklbw mm1, mm1
402     pshufw    mm2, mm0, 0xFA
403     pshufw    mm3, mm1, 0xFA
404     punpcklbw mm0, mm0
405     punpcklbw mm1, mm1
406     ADD_DC    mm0, mm1, r0
407     ADD_DC    mm2, mm3, r0+8
408     add       r1, 8
409     add       r0, FDEC_STRIDE*4
410     dec       r2
411     jg .loop
412     REP_RET
413
414 %macro IDCT_DC_STORE 3
415     movdqa    xmm4, [r0+%1+FDEC_STRIDE*0]
416     movdqa    xmm5, [r0+%1+FDEC_STRIDE*1]
417     movdqa    xmm6, [r0+%1+FDEC_STRIDE*2]
418     movdqa    xmm7, [r0+%1+FDEC_STRIDE*3]
419     paddusb   xmm4, %2
420     paddusb   xmm5, %2
421     paddusb   xmm6, %2
422     paddusb   xmm7, %2
423     psubusb   xmm4, %3
424     psubusb   xmm5, %3
425     psubusb   xmm6, %3
426     psubusb   xmm7, %3
427     movdqa    [r0+%1+FDEC_STRIDE*0], xmm4
428     movdqa    [r0+%1+FDEC_STRIDE*1], xmm5
429     movdqa    [r0+%1+FDEC_STRIDE*2], xmm6
430     movdqa    [r0+%1+FDEC_STRIDE*3], xmm7
431 %endmacro
432
433 cglobal add16x16_idct_dc_sse2, 2,2,8
434     call .loop
435     add       r0, FDEC_STRIDE*4
436 %ifdef WIN64
437     call .loop
438     RET
439 %endif
440 .loop:
441     add       r0, FDEC_STRIDE*4
442     movq      xmm0, [r1+0]
443     movq      xmm2, [r1+8]
444     add       r1, 16
445     punpcklwd xmm0, xmm0
446     punpcklwd xmm2, xmm2
447     pxor      xmm1, xmm1
448     pxor      xmm3, xmm3
449     paddw     xmm0, [pw_32]
450     paddw     xmm2, [pw_32]
451     psraw     xmm0, 6
452     psraw     xmm2, 6
453     psubw     xmm1, xmm0
454     psubw     xmm3, xmm2
455     packuswb  xmm0, xmm1
456     packuswb  xmm2, xmm3
457     movdqa    xmm1, xmm0
458     movdqa    xmm3, xmm2
459     punpcklbw xmm0, xmm0
460     punpcklbw xmm2, xmm2
461     punpckhbw xmm1, xmm1
462     punpckhbw xmm3, xmm3
463     IDCT_DC_STORE FDEC_STRIDE*-4, xmm0, xmm1
464     IDCT_DC_STORE 0, xmm2, xmm3
465     ret
466
467 cglobal add16x16_idct_dc_ssse3, 2,2,8
468     call .loop
469     add       r0, FDEC_STRIDE*4
470 %ifdef WIN64
471     call .loop
472     RET
473 %endif
474 .loop:
475     add       r0, FDEC_STRIDE*4
476     movdqa    xmm0, [r1]
477     add       r1, 16
478     pxor      xmm1, xmm1
479     paddw     xmm0, [pw_32]
480     psraw     xmm0, 6
481     psubw     xmm1, xmm0
482     movdqa    xmm5, [ pb_idctdc_unpack]
483     movdqa    xmm6, [pb_idctdc_unpack2]
484     packuswb  xmm0, xmm0
485     packuswb  xmm1, xmm1
486     movdqa    xmm2, xmm0
487     movdqa    xmm3, xmm1
488     pshufb    xmm0, xmm5
489     pshufb    xmm2, xmm6
490     pshufb    xmm1, xmm5
491     pshufb    xmm3, xmm6
492     IDCT_DC_STORE FDEC_STRIDE*-4, xmm0, xmm1
493     IDCT_DC_STORE 0, xmm2, xmm3
494     ret
495
496 ;-----------------------------------------------------------------------------
497 ; void sub8x8_dct_dc( int16_t dct[2][2], uint8_t *pix1, uint8_t *pix2 )
498 ;-----------------------------------------------------------------------------
499
500 %macro DCTDC_2ROW_MMX 3
501     movq      %1, [r1+FENC_STRIDE*(0+%3)]
502     movq      m1, [r1+FENC_STRIDE*(1+%3)]
503     movq      m2, [r2+FDEC_STRIDE*(0+%3)]
504     movq      m3, [r2+FDEC_STRIDE*(1+%3)]
505     movq      %2, %1
506     punpckldq %1, m1
507     punpckhdq %2, m1
508     movq      m1, m2
509     punpckldq m2, m3
510     punpckhdq m1, m3
511     pxor      m3, m3
512     psadbw    %1, m3
513     psadbw    %2, m3
514     psadbw    m2, m3
515     psadbw    m1, m3
516     psubw     %1, m2
517     psubw     %2, m1
518 %endmacro
519
520 %macro DCT2x2 2 ; reg s1/s0 (!=m1), reg s3/s2
521     pshufw    mm1, %1, 10100000b  ;  s1  s1  s0  s0
522     pshufw    mm0, %2, 10110001b  ;  s3  __  s2  __
523     paddw     mm1, %2             ;  s1 s13  s0 s02
524     psubw     mm1, mm0            ; d13 s13 d02 s02
525     pshufw    mm0, mm1, 01000100b ; d02 s02 d02 s02
526     psrlq     mm1, 32             ;  __  __ d13 s13
527     paddw     mm0, mm1            ; d02 s02 d02+d13 s02+s13
528     psllq     mm1, 32             ; d13 s13
529     psubw     mm0, mm1            ; d02-d13 s02-s13 d02+d13 s02+s13
530 %endmacro
531
532 INIT_MMX
533 cglobal sub8x8_dct_dc_mmxext, 3,3
534     DCTDC_2ROW_MMX m0, m4, 0
535     DCTDC_2ROW_MMX m5, m6, 2
536     paddw     m0, m5
537     paddw     m4, m6
538     punpckldq m0, m4
539     add       r1, FENC_STRIDE*4
540     add       r2, FDEC_STRIDE*4
541     DCTDC_2ROW_MMX m7, m4, 0
542     DCTDC_2ROW_MMX m5, m6, 2
543     paddw     m7, m5
544     paddw     m4, m6
545     punpckldq m7, m4
546     DCT2x2    m0, m7
547     movq    [r0], m0
548     ret
549
550 INIT_XMM
551 %macro DCTDC_2ROW_SSE2 3
552     movq      m0, [r1+FENC_STRIDE*(0+%1)]
553     movq      m1, [r1+FENC_STRIDE*(1+%1)]
554     movq      m2, [r2+FDEC_STRIDE*(0+%1)]
555     movq      m3, [r2+FDEC_STRIDE*(1+%1)]
556     punpckldq m0, m1
557     punpckldq m2, m3
558     psadbw    m0, m7
559     psadbw    m2, m7
560 %if %2
561     paddw     %3, m0
562     paddw     m6, m2
563 %else
564     SWAP      %3, m0
565     SWAP      m6, m2
566 %endif
567 %endmacro
568
569 cglobal sub8x8_dct_dc_sse2, 3,3,8
570     pxor     m7, m7
571     DCTDC_2ROW_SSE2 0, 0, m4
572     DCTDC_2ROW_SSE2 2, 1, m4
573     add      r1, FENC_STRIDE*4
574     add      r2, FDEC_STRIDE*4
575     psubd    m4, m6
576     DCTDC_2ROW_SSE2 0, 0, m5
577     DCTDC_2ROW_SSE2 2, 1, m5
578     psubd    m5, m6
579     packssdw m4, m5
580     movhlps  m5, m4
581     movdq2q mm0, m4
582     movdq2q mm7, m5
583     DCT2x2  mm0, mm7
584     movq   [r0], mm0
585     RET
586
587 ;-----------------------------------------------------------------------------
588 ; void zigzag_scan_8x8_frame( int16_t level[64], int16_t dct[8][8] )
589 ;-----------------------------------------------------------------------------
590 %macro SCAN_8x8 1
591 cglobal zigzag_scan_8x8_frame_%1, 2,2,8
592     movdqa    xmm0, [r1]
593     movdqa    xmm1, [r1+16]
594     movdq2q    mm0, xmm0
595     PALIGNR   xmm1, xmm1, 14, xmm2
596     movdq2q    mm1, xmm1
597
598     movdqa    xmm2, [r1+32]
599     movdqa    xmm3, [r1+48]
600     PALIGNR   xmm2, xmm2, 12, xmm4
601     movdq2q    mm2, xmm2
602     PALIGNR   xmm3, xmm3, 10, xmm4
603     movdq2q    mm3, xmm3
604
605     punpckhwd xmm0, xmm1
606     punpckhwd xmm2, xmm3
607
608     movq       mm4, mm1
609     movq       mm5, mm1
610     movq       mm6, mm2
611     movq       mm7, mm3
612     punpckhwd  mm1, mm0
613     psllq      mm0, 16
614     psrlq      mm3, 16
615     punpckhdq  mm1, mm1
616     punpckhdq  mm2, mm0
617     punpcklwd  mm0, mm4
618     punpckhwd  mm4, mm3
619     punpcklwd  mm4, mm2
620     punpckhdq  mm0, mm2
621     punpcklwd  mm6, mm3
622     punpcklwd  mm5, mm7
623     punpcklwd  mm5, mm6
624
625     movdqa    xmm4, [r1+64]
626     movdqa    xmm5, [r1+80]
627     movdqa    xmm6, [r1+96]
628     movdqa    xmm7, [r1+112]
629
630     movq [r0+2*00], mm0
631     movq [r0+2*04], mm4
632     movd [r0+2*08], mm1
633     movq [r0+2*36], mm5
634     movq [r0+2*46], mm6
635
636     PALIGNR   xmm4, xmm4, 14, xmm3
637     movdq2q    mm4, xmm4
638     PALIGNR   xmm5, xmm5, 12, xmm3
639     movdq2q    mm5, xmm5
640     PALIGNR   xmm6, xmm6, 10, xmm3
641     movdq2q    mm6, xmm6
642 %ifidn %1, ssse3
643     PALIGNR   xmm7, xmm7, 8, xmm3
644     movdq2q    mm7, xmm7
645 %else
646     movhlps   xmm3, xmm7
647     punpcklqdq xmm7, xmm7
648     movdq2q    mm7, xmm3
649 %endif
650
651     punpckhwd xmm4, xmm5
652     punpckhwd xmm6, xmm7
653
654     movq       mm0, mm4
655     movq       mm1, mm5
656     movq       mm3, mm7
657     punpcklwd  mm7, mm6
658     psrlq      mm6, 16
659     punpcklwd  mm4, mm6
660     punpcklwd  mm5, mm4
661     punpckhdq  mm4, mm3
662     punpcklwd  mm3, mm6
663     punpckhwd  mm3, mm4
664     punpckhwd  mm0, mm1
665     punpckldq  mm4, mm0
666     punpckhdq  mm0, mm6
667     pshufw     mm4, mm4, 0x6c
668
669     movq [r0+2*14], mm4
670     movq [r0+2*25], mm0
671     movd [r0+2*54], mm7
672     movq [r0+2*56], mm5
673     movq [r0+2*60], mm3
674
675     movdqa    xmm3, xmm0
676     movdqa    xmm7, xmm4
677     punpckldq xmm0, xmm2
678     punpckldq xmm4, xmm6
679     punpckhdq xmm3, xmm2
680     punpckhdq xmm7, xmm6
681     pshufhw   xmm0, xmm0, 0x1b
682     pshuflw   xmm4, xmm4, 0x1b
683     pshufhw   xmm3, xmm3, 0x1b
684     pshuflw   xmm7, xmm7, 0x1b
685
686     movlps [r0+2*10], xmm0
687     movhps [r0+2*17], xmm0
688     movlps [r0+2*21], xmm3
689     movlps [r0+2*28], xmm4
690     movhps [r0+2*32], xmm3
691     movhps [r0+2*39], xmm4
692     movlps [r0+2*43], xmm7
693     movhps [r0+2*50], xmm7
694
695     RET
696 %endmacro
697
698 INIT_XMM
699 %define PALIGNR PALIGNR_MMX
700 SCAN_8x8 sse2
701 %define PALIGNR PALIGNR_SSSE3
702 SCAN_8x8 ssse3
703
704 ;-----------------------------------------------------------------------------
705 ; void zigzag_scan_8x8_frame( int16_t level[64], int16_t dct[8][8] )
706 ;-----------------------------------------------------------------------------
707 cglobal zigzag_scan_8x8_frame_mmxext, 2,2
708     movq       mm0, [r1]
709     movq       mm1, [r1+2*8]
710     movq       mm2, [r1+2*14]
711     movq       mm3, [r1+2*21]
712     movq       mm4, [r1+2*28]
713     movq       mm5, mm0
714     movq       mm6, mm1
715     psrlq      mm0, 16
716     punpckldq  mm1, mm1
717     punpcklwd  mm5, mm6
718     punpckhwd  mm1, mm3
719     punpckhwd  mm6, mm0
720     punpckldq  mm5, mm0
721     movq       mm7, [r1+2*52]
722     movq       mm0, [r1+2*60]
723     punpckhwd  mm1, mm2
724     punpcklwd  mm2, mm4
725     punpckhwd  mm4, mm3
726     punpckldq  mm3, mm3
727     punpckhwd  mm3, mm2
728     movq      [r0], mm5
729     movq  [r0+2*4], mm1
730     movq  [r0+2*8], mm6
731     punpcklwd  mm6, mm0
732     punpcklwd  mm6, mm7
733     movq       mm1, [r1+2*32]
734     movq       mm5, [r1+2*39]
735     movq       mm2, [r1+2*46]
736     movq [r0+2*35], mm3
737     movq [r0+2*47], mm4
738     punpckhwd  mm7, mm0
739     psllq      mm0, 16
740     movq       mm3, mm5
741     punpcklwd  mm5, mm1
742     punpckhwd  mm1, mm2
743     punpckhdq  mm3, mm3
744     movq [r0+2*52], mm6
745     movq [r0+2*13], mm5
746     movq       mm4, [r1+2*11]
747     movq       mm6, [r1+2*25]
748     punpcklwd  mm5, mm7
749     punpcklwd  mm1, mm3
750     punpckhdq  mm0, mm7
751     movq       mm3, [r1+2*4]
752     movq       mm7, [r1+2*18]
753     punpcklwd  mm2, mm5
754     movq [r0+2*25], mm1
755     movq       mm1, mm4
756     movq       mm5, mm6
757     punpcklwd  mm4, mm3
758     punpcklwd  mm6, mm7
759     punpckhwd  mm1, mm3
760     punpckhwd  mm5, mm7
761     movq       mm3, mm6
762     movq       mm7, mm5
763     punpckldq  mm6, mm4
764     punpckldq  mm5, mm1
765     punpckhdq  mm3, mm4
766     punpckhdq  mm7, mm1
767     movq       mm4, [r1+2*35]
768     movq       mm1, [r1+2*49]
769     pshufw     mm6, mm6, 0x1b
770     pshufw     mm5, mm5, 0x1b
771     movq [r0+2*60], mm0
772     movq [r0+2*56], mm2
773     movq       mm0, [r1+2*42]
774     movq       mm2, [r1+2*56]
775     movq [r0+2*17], mm3
776     movq [r0+2*32], mm7
777     movq [r0+2*10], mm6
778     movq [r0+2*21], mm5
779     movq       mm3, mm0
780     movq       mm7, mm2
781     punpcklwd  mm0, mm4
782     punpcklwd  mm2, mm1
783     punpckhwd  mm3, mm4
784     punpckhwd  mm7, mm1
785     movq       mm4, mm2
786     movq       mm1, mm7
787     punpckhdq  mm2, mm0
788     punpckhdq  mm7, mm3
789     punpckldq  mm4, mm0
790     punpckldq  mm1, mm3
791     pshufw     mm2, mm2, 0x1b
792     pshufw     mm7, mm7, 0x1b
793     movq [r0+2*28], mm4
794     movq [r0+2*43], mm1
795     movq [r0+2*39], mm2
796     movq [r0+2*50], mm7
797     RET
798
799 ;-----------------------------------------------------------------------------
800 ; void zigzag_scan_4x4_frame( int16_t level[16], int16_t dct[4][4] )
801 ;-----------------------------------------------------------------------------
802 cglobal zigzag_scan_4x4_frame_mmx, 2,2
803     movq       mm0, [r1]
804     movq       mm1, [r1+8]
805     movq       mm2, [r1+16]
806     movq       mm3, [r1+24]
807     movq       mm4, mm0
808     movq       mm5, mm1
809     movq       mm6, mm2
810     movq       mm7, mm3
811     psllq      mm3, 16
812     psrlq      mm0, 16
813     punpckldq  mm2, mm2
814     punpckhdq  mm1, mm1
815     punpcklwd  mm4, mm5
816     punpcklwd  mm5, mm3
817     punpckldq  mm4, mm0
818     punpckhwd  mm5, mm2
819     punpckhwd  mm0, mm6
820     punpckhwd  mm6, mm7
821     punpcklwd  mm1, mm0
822     punpckhdq  mm3, mm6
823     movq      [r0], mm4
824     movq    [r0+8], mm5
825     movq   [r0+16], mm1
826     movq   [r0+24], mm3
827     RET
828
829 ;-----------------------------------------------------------------------------
830 ; void zigzag_scan_4x4_frame( int16_t level[16], int16_t dct[4][4] )
831 ;-----------------------------------------------------------------------------
832 cglobal zigzag_scan_4x4_frame_ssse3, 2,2
833     movdqa    xmm1, [r1+16]
834     movdqa    xmm0, [r1]
835     pshufb    xmm1, [pb_scan4frameb]
836     pshufb    xmm0, [pb_scan4framea]
837     movdqa    xmm2, xmm1
838     psrldq    xmm1, 6
839     palignr   xmm2, xmm0, 6
840     pslldq    xmm0, 10
841     palignr   xmm1, xmm0, 10
842     movdqa    [r0], xmm2
843     movdqa [r0+16], xmm1
844     RET
845
846 ;-----------------------------------------------------------------------------
847 ; void zigzag_scan_4x4_field( int16_t level[16], int16_t dct[4][4] )
848 ;-----------------------------------------------------------------------------
849 ; sse2 is only 1 cycle faster, and ssse3/pshufb is slower on core2
850 cglobal zigzag_scan_4x4_field_mmxext, 2,3
851     pshufw     mm0, [r1+4], 0xd2
852     movq       mm1, [r1+16]
853     movq       mm2, [r1+24]
854     movq    [r0+4], mm0
855     movq   [r0+16], mm1
856     movq   [r0+24], mm2
857     mov        r2d, [r1]
858     mov       [r0], r2d
859     mov        r2d, [r1+12]
860     mov    [r0+12], r2d
861     RET
862
863 ;-----------------------------------------------------------------------------
864 ; void zigzag_scan_8x8_field( int16_t level[64], int16_t dct[8][8] )
865 ;-----------------------------------------------------------------------------
866
867 ; Output order:
868 ;  0  1  2  8  9  3  4 10
869 ; 16 11  5  6  7 12 17 24
870 ; 18 13 14 15 19 25 32 26
871 ; 20 21 22 23 27 33 40 34
872 ; 28 29 30 31 35 41 48 42
873 ; 36 37 38 39 43 49 50 44
874 ; 45 46 47 51 56 57 52 53
875 ; 54 55 58 59 60 61 62 63
876
877 cglobal zigzag_scan_8x8_field_mmxext, 2,3
878     movq       mm0, [r1+2*0]        ; 03 02 01 00
879     movq       mm1, [r1+2*4]        ; 07 06 05 04
880     movq       mm2, [r1+2*8]        ; 11 10 09 08
881     pshufw     mm3, mm0, 011111111b ; 03 03 03 03
882     movd        r2, mm2             ; 09 08
883     pshufw     mm2, mm2, 000111001b ; 08 11 10 09
884     punpcklwd  mm3, mm1             ; 05 03 04 03
885     pinsrw     mm0, r2, 3           ; 08 02 01 00
886     movq       mm4, mm2
887     punpcklwd  mm2, mm3             ; 04 10 03 09
888     pshufw     mm2, mm2, 010110100b ; 10 04 03 09
889     movq  [r0+2*0], mm0             ; 08 02 01 00
890     movq  [r0+2*4], mm2             ; 10 04 03 09
891     movq       mm3, [r1+2*12]       ; 15 14 13 12
892     movq       mm5, [r1+2*16]       ; 19 18 17 16
893     punpckldq  mm6, mm5             ; 17 16 XX XX
894     psrlq      mm1, 16              ; XX 07 06 05
895     punpckhwd  mm6, mm4             ; 08 17 11 16
896     punpckldq  mm6, mm1             ; 06 05 11 16
897     movq  [r0+2*8], mm6             ; 06 05 11 16
898     psrlq      mm1, 16              ; XX XX 07 06
899     punpcklwd  mm1, mm5             ; 17 07 16 06
900     movq       mm0, [r1+2*20]       ; 23 22 21 20
901     movq       mm2, [r1+2*24]       ; 27 26 25 24
902     movq       mm6, mm3
903     punpckhdq  mm1, mm1             ; 17 07 17 07
904     punpcklwd  mm6, mm2             ; 25 13 24 12
905     pextrw      r2, mm5, 2
906     movq [r0+2*24], mm0             ; 23 22 21 20
907     punpcklwd  mm1, mm6             ; 24 17 12 07
908     movq [r0+2*12], mm1
909     pinsrw     mm3, r2, 0           ; 15 14 13 18
910     movq [r0+2*16], mm3             ; 15 14 13 18
911     movq       mm7, [r1+2*28]
912     movq       mm0, [r1+2*32]       ; 35 34 33 32
913     psrlq      mm5, 48              ; XX XX XX 19
914     pshufw     mm1, mm2, 011111001b ; 27 27 26 25
915     punpcklwd  mm5, mm0             ; 33 XX 32 19
916     psrlq      mm2, 48              ; XX XX XX 27
917     punpcklwd  mm5, mm1             ; 26 32 25 19
918     movq [r0+2*32], mm7
919     movq [r0+2*20], mm5             ; 26 32 25 19
920     movq       mm7, [r1+2*36]
921     movq       mm1, [r1+2*40]       ; 43 42 41 40
922     pshufw     mm3, mm0, 011111001b ; 35 35 34 33
923     punpcklwd  mm2, mm1             ; 41 XX 40 27
924     movq [r0+2*40], mm7
925     punpcklwd  mm2, mm3             ; 34 40 33 27
926     movq [r0+2*28], mm2
927     movq       mm7, [r1+2*44]       ; 47 46 45 44
928     movq       mm2, [r1+2*48]       ; 51 50 49 48
929     psrlq      mm0, 48              ; XX XX XX 35
930     punpcklwd  mm0, mm2             ; 49 XX 48 35
931     pshufw     mm3, mm1, 011111001b ; 43 43 42 41
932     punpcklwd  mm0, mm3             ; 42 48 41 35
933     movq [r0+2*36], mm0
934     pextrw      r2, mm2, 3          ; 51
935     psrlq      mm1, 48              ; XX XX XX 43
936     punpcklwd  mm1, mm7             ; 45 XX 44 43
937     psrlq      mm2, 16              ; XX 51 50 49
938     punpcklwd  mm1, mm2             ; 50 44 49 43
939     pshufw     mm1, mm1, 010110100b ; 44 50 49 43
940     movq [r0+2*44], mm1
941     psrlq      mm7, 16              ; XX 47 46 45
942     pinsrw     mm7, r2, 3           ; 51 47 46 45
943     movq [r0+2*48], mm7
944     movq       mm0, [r1+2*56]       ; 59 58 57 56
945     movq       mm1, [r1+2*52]       ; 55 54 53 52
946     movq       mm2, mm0
947     movq       mm7, [r1+2*60]
948     punpckldq  mm2, mm1             ; 53 52 57 56
949     punpckhdq  mm1, mm0             ; 59 58 55 54
950     movq [r0+2*52], mm2
951     movq [r0+2*56], mm1
952     movq [r0+2*60], mm7
953     RET
954
955 ;-----------------------------------------------------------------------------
956 ; void zigzag_sub_4x4_frame( int16_t level[16], const uint8_t *src, uint8_t *dst )
957 ;-----------------------------------------------------------------------------
958 %macro ZIGZAG_SUB_4x4 2
959 %ifidn %1, ac
960 cglobal zigzag_sub_4x4%1_%2_ssse3, 4,4,8
961 %else
962 cglobal zigzag_sub_4x4%1_%2_ssse3, 3,3,8
963 %endif
964     movd      xmm0, [r1+0*FENC_STRIDE]
965     movd      xmm1, [r1+1*FENC_STRIDE]
966     movd      xmm2, [r1+2*FENC_STRIDE]
967     movd      xmm3, [r1+3*FENC_STRIDE]
968     movd      xmm4, [r2+0*FDEC_STRIDE]
969     movd      xmm5, [r2+1*FDEC_STRIDE]
970     movd      xmm6, [r2+2*FDEC_STRIDE]
971     movd      xmm7, [r2+3*FDEC_STRIDE]
972     movd      [r2+0*FDEC_STRIDE], xmm0
973     movd      [r2+1*FDEC_STRIDE], xmm1
974     movd      [r2+2*FDEC_STRIDE], xmm2
975     movd      [r2+3*FDEC_STRIDE], xmm3
976     punpckldq xmm0, xmm1
977     punpckldq xmm2, xmm3
978     punpckldq xmm4, xmm5
979     punpckldq xmm6, xmm7
980     punpcklqdq xmm0, xmm2
981     punpcklqdq xmm4, xmm6
982 %ifidn %2, frame
983     movdqa    xmm7, [pb_sub4frame]
984 %else
985     movdqa    xmm7, [pb_sub4field]
986 %endif
987     pshufb    xmm0, xmm7
988     pshufb    xmm4, xmm7
989     pxor      xmm6, xmm6
990     movdqa    xmm1, xmm0
991     movdqa    xmm5, xmm4
992     punpcklbw xmm0, xmm6
993     punpckhbw xmm1, xmm6
994     punpcklbw xmm4, xmm6
995     punpckhbw xmm5, xmm6
996     psubw     xmm0, xmm4
997     psubw     xmm1, xmm5
998 %ifidn %1, ac
999     movd       r2d, xmm0
1000     pand      xmm0, [pb_subacmask]
1001 %endif
1002     movdqa    [r0], xmm0
1003     pxor      xmm2, xmm2
1004     movdqa [r0+16], xmm1
1005     por       xmm0, xmm1
1006     pcmpeqb   xmm0, xmm2
1007     pmovmskb   eax, xmm0
1008 %ifidn %1, ac
1009     mov       [r3], r2w
1010 %endif
1011     sub        eax, 0xffff
1012     shr        eax, 31
1013     RET
1014 %endmacro
1015
1016 ZIGZAG_SUB_4x4   , frame
1017 ZIGZAG_SUB_4x4 ac, frame
1018 ZIGZAG_SUB_4x4   , field
1019 ZIGZAG_SUB_4x4 ac, field
1020
1021 ;-----------------------------------------------------------------------------
1022 ; void zigzag_interleave_8x8_cavlc( int16_t *dst, int16_t *src, uint8_t *nnz )
1023 ;-----------------------------------------------------------------------------
1024
1025 %macro INTERLEAVE 1
1026     movq   m0, [r1+%1*4+ 0]
1027     movq   m1, [r1+%1*4+ 8]
1028     movq   m2, [r1+%1*4+16]
1029     movq   m3, [r1+%1*4+24]
1030     TRANSPOSE4x4W 0,1,2,3,4
1031     movq   [r0+%1+ 0], m0
1032     movq   [r0+%1+32], m1
1033     movq   [r0+%1+64], m2
1034     movq   [r0+%1+96], m3
1035 %if %1
1036     packsswb m0, m1
1037     por    m6, m2
1038     por    m7, m3
1039     por    m5, m0
1040 %else
1041     packsswb m0, m1
1042     SWAP   m5, m0
1043     SWAP   m6, m2
1044     SWAP   m7, m3
1045 %endif
1046 %endmacro
1047
1048 INIT_MMX
1049 cglobal zigzag_interleave_8x8_cavlc_mmx, 3,3
1050     INTERLEAVE  0
1051     INTERLEAVE  8
1052     INTERLEAVE 16
1053     INTERLEAVE 24
1054     packsswb m6, m7
1055     packsswb m5, m6
1056     packsswb m5, m5
1057     pxor     m0, m0
1058     pcmpeqb  m5, m0
1059     paddb    m5, [pb_1]
1060     movd    r0d, m5
1061     mov  [r2+0], r0w
1062     shr     r0d, 16
1063     mov  [r2+8], r0w
1064     RET
1065
1066 %macro INTERLEAVE_XMM 1
1067     mova   m0, [r1+%1*4+ 0]
1068     mova   m1, [r1+%1*4+16]
1069     mova   m4, [r1+%1*4+32]
1070     mova   m5, [r1+%1*4+48]
1071     SBUTTERFLY wd, 0, 1, 6
1072     SBUTTERFLY wd, 4, 5, 7
1073     SBUTTERFLY wd, 0, 1, 6
1074     SBUTTERFLY wd, 4, 5, 7
1075     movq   [r0+%1+  0], m0
1076     movhps [r0+%1+ 32], m0
1077     movq   [r0+%1+ 64], m1
1078     movhps [r0+%1+ 96], m1
1079     movq   [r0+%1+  8], m4
1080     movhps [r0+%1+ 40], m4
1081     movq   [r0+%1+ 72], m5
1082     movhps [r0+%1+104], m5
1083 %if %1
1084     por    m2, m0
1085     por    m3, m1
1086     por    m2, m4
1087     por    m3, m5
1088 %else
1089     SWAP 0,2
1090     SWAP 3,1
1091     por    m2, m4
1092     por    m3, m5
1093 %endif
1094 %endmacro
1095
1096 INIT_XMM
1097 cglobal zigzag_interleave_8x8_cavlc_sse2, 3,3,8
1098     INTERLEAVE_XMM  0
1099     INTERLEAVE_XMM 16
1100     packsswb m2, m3
1101     pxor     m5, m5
1102     packsswb m2, m2
1103     packsswb m2, m2
1104     pcmpeqb  m5, m2
1105     paddb    m5, [pb_1]
1106     movd    r0d, m5
1107     mov  [r2+0], r0w
1108     shr     r0d, 16
1109     mov  [r2+8], r0w
1110     RET
1111