]> git.sesse.net Git - x264/blob - common/x86/dct-32.asm
b8f7832d8627a0e9f3b1b3021a4d8adc7091e23a
[x264] / common / x86 / dct-32.asm
1 ;*****************************************************************************
2 ;* dct-32.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2003-2008 x264 project
5 ;*
6 ;* Authors: Laurent Aimar <fenrir@via.ecp.fr> (initial version)
7 ;*          Loren Merritt <lorenm@u.washington.edu> (misc)
8 ;*          Min Chen <chenm001.163.com> (converted to nasm)
9 ;*          Christian Heine <sennindemokrit@gmx.net> (dct8/idct8 functions)
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 SECTION_RODATA
30
31 pw_32: times 8 dw 32
32
33 SECTION .text
34
35 %macro SBUTTERFLY 4
36     mova       m%4, m%2
37     punpckl%1  m%2, m%3
38     punpckh%1  m%4, m%3
39     SWAP %3, %4
40 %endmacro
41
42 %macro TRANSPOSE4x4W 5
43     SBUTTERFLY wd, %1, %2, %5
44     SBUTTERFLY wd, %3, %4, %5
45     SBUTTERFLY dq, %1, %3, %5
46     SBUTTERFLY dq, %2, %4, %5
47     SWAP %2, %3
48 %endmacro
49
50 ; in: m0..m7
51 ; out: 0,4,6 in mem, rest in regs
52 %macro DCT8_1D 9
53     SUMSUB_BA  m%8, m%1      ; %8 = s07, %1 = d07
54     SUMSUB_BA  m%7, m%2      ; %7 = s16, %2 = d16
55     SUMSUB_BA  m%6, m%3      ; %6 = s25, %3 = d25
56     SUMSUB_BA  m%5, m%4      ; %5 = s34, %4 = d34
57     SUMSUB_BA  m%5, m%8      ; %5 = a0,  %8 = a2
58     SUMSUB_BA  m%6, m%7      ; %6 = a1,  %7 = a3
59     SUMSUB_BA  m%6, m%5      ; %6 = dst0, %5 = dst4
60     mova    [%9+0x00], m%6
61     mova    [%9+0x40], m%5
62     mova    m%6, m%7         ; a3
63     psraw   m%6, 1           ; a3>>1
64     paddw   m%6, m%8         ; a2 + (a3>>1)
65     psraw   m%8, 1           ; a2>>1
66     psubw   m%8, m%7         ; (a2>>1) - a3
67     mova    [%9+0x60], m%8
68     mova    m%5, m%3
69     psraw   m%5, 1
70     paddw   m%5, m%3         ; d25+(d25>>1)
71     mova    m%7, m%1
72     psubw   m%7, m%4         ; a5 = d07-d34-(d25+(d25>>1))
73     psubw   m%7, m%5
74     mova    m%5, m%2
75     psraw   m%5, 1
76     paddw   m%5, m%2         ; d16+(d16>>1)
77     mova    m%8, m%1
78     paddw   m%8, m%4
79     psubw   m%8, m%5         ; a6 = d07+d34-(d16+(d16>>1))
80     mova    m%5, m%1
81     psraw   m%5, 1
82     paddw   m%5, m%1         ; d07+(d07>>1)
83     paddw   m%5, m%2
84     paddw   m%5, m%3         ; a4 = d16+d25+(d07+(d07>>1))
85     mova    m%1, m%4
86     psraw   m%1, 1
87     paddw   m%1, m%4         ; d34+(d34>>1)
88     paddw   m%1, m%2
89     psubw   m%1, m%3         ; a7 = d16-d25+(d34+(d34>>1))
90     mova    m%4, m%1
91     psraw   m%4, 2
92     paddw   m%4, m%5         ; a4 + (a7>>2)
93     mova    m%3, m%8
94     psraw   m%3, 2
95     paddw   m%3, m%7         ; a5 + (a6>>2)
96     psraw   m%5, 2
97     psraw   m%7, 2
98     psubw   m%5, m%1         ; (a4>>2) - a7
99     psubw   m%8, m%7         ; a6 - (a5>>2)
100     SWAP %2, %4, %3, %6, %8, %5
101 %endmacro
102
103 ; in: 0,4 in mem, rest in regs
104 ; out: m0..m7
105 %macro IDCT8_1D 9
106     mova      m%1, m%3
107     mova      m%5, m%7
108     psraw     m%3, 1
109     psraw     m%7, 1
110     psubw     m%3, m%5
111     paddw     m%7, m%1
112     mova      m%5, m%2
113     psraw     m%5, 1
114     paddw     m%5, m%2
115     paddw     m%5, m%4
116     paddw     m%5, m%6
117     mova      m%1, m%6
118     psraw     m%1, 1
119     paddw     m%1, m%6
120     paddw     m%1, m%8
121     psubw     m%1, m%2
122     psubw     m%2, m%4
123     psubw     m%6, m%4
124     paddw     m%2, m%8
125     psubw     m%6, m%8
126     psraw     m%4, 1
127     psraw     m%8, 1
128     psubw     m%2, m%4
129     psubw     m%6, m%8
130     mova      m%4, m%5
131     mova      m%8, m%1
132     psraw     m%4, 2
133     psraw     m%8, 2
134     paddw     m%4, m%6
135     paddw     m%8, m%2
136     psraw     m%6, 2
137     psraw     m%2, 2
138     psubw     m%5, m%6
139     psubw     m%2, m%1
140     mova      m%1, [%9+0x00]
141     mova      m%6, [%9+0x40]
142     SUMSUB_BA m%6, m%1
143     SUMSUB_BA m%7, m%6
144     SUMSUB_BA m%3, m%1
145     SUMSUB_BA m%5, m%7
146     SUMSUB_BA m%2, m%3
147     SUMSUB_BA m%8, m%1
148     SUMSUB_BA m%4, m%6
149     SWAP %1, %5, %6
150     SWAP %3, %8, %7
151 %endmacro
152
153 INIT_MMX
154 ALIGN 16
155 load_diff_4x8_mmx:
156     LOAD_DIFF m0, m7, none, [r1+0*FENC_STRIDE], [r2+0*FDEC_STRIDE]
157     LOAD_DIFF m1, m7, none, [r1+1*FENC_STRIDE], [r2+1*FDEC_STRIDE]
158     LOAD_DIFF m2, m7, none, [r1+2*FENC_STRIDE], [r2+2*FDEC_STRIDE]
159     LOAD_DIFF m3, m7, none, [r1+3*FENC_STRIDE], [r2+3*FDEC_STRIDE]
160     LOAD_DIFF m4, m7, none, [r1+4*FENC_STRIDE], [r2+4*FDEC_STRIDE]
161     LOAD_DIFF m5, m7, none, [r1+5*FENC_STRIDE], [r2+5*FDEC_STRIDE]
162     movq  [r0], m0
163     LOAD_DIFF m6, m7, none, [r1+6*FENC_STRIDE], [r2+6*FDEC_STRIDE]
164     LOAD_DIFF m7, m0, none, [r1+7*FENC_STRIDE], [r2+7*FDEC_STRIDE]
165     movq  m0, [r0]
166     ret
167
168 INIT_MMX
169 ALIGN 16
170 dct8_mmx:
171     DCT8_1D 0,1,2,3,4,5,6,7,r0
172     SAVE_MM_PERMUTATION dct8_mmx
173     ret
174
175 %macro SPILL_SHUFFLE 3-* ; ptr, list of regs, list of memory offsets
176     %xdefine %%base %1
177     %rep %0/2
178     %xdefine %%tmp m%2
179     %rotate %0/2
180     mova [%%base + %2*16], %%tmp
181     %rotate 1-%0/2
182     %endrep
183 %endmacro
184
185 %macro UNSPILL_SHUFFLE 3-*
186     %xdefine %%base %1
187     %rep %0/2
188     %xdefine %%tmp m%2
189     %rotate %0/2
190     mova %%tmp, [%%base + %2*16]
191     %rotate 1-%0/2
192     %endrep
193 %endmacro
194
195 %macro SPILL 2+ ; assume offsets are the same as reg numbers
196     SPILL_SHUFFLE %1, %2, %2
197 %endmacro
198
199 %macro UNSPILL 2+
200     UNSPILL_SHUFFLE %1, %2, %2
201 %endmacro
202
203 ;-----------------------------------------------------------------------------
204 ; void x264_sub8x8_dct8_mmx( int16_t dct[8][8], uint8_t *pix1, uint8_t *pix2 )
205 ;-----------------------------------------------------------------------------
206 cglobal x264_sub8x8_dct8_mmx, 3,3
207 global x264_sub8x8_dct8_mmx %+ .skip_prologue
208 .skip_prologue:
209     INIT_MMX
210     call load_diff_4x8_mmx
211     call dct8_mmx
212     UNSPILL r0, 0
213     TRANSPOSE4x4W 0,1,2,3,4
214     SPILL r0, 0,1,2,3
215     UNSPILL r0, 4,6
216     TRANSPOSE4x4W 4,5,6,7,0
217     SPILL r0, 4,5,6,7
218     INIT_MMX
219     add   r1, 4
220     add   r2, 4
221     add   r0, 8
222     call load_diff_4x8_mmx
223     sub   r1, 4
224     sub   r2, 4
225     call dct8_mmx
226     sub   r0, 8
227     UNSPILL r0+8, 4,6
228     TRANSPOSE4x4W 4,5,6,7,0
229     SPILL r0+8, 4,5,6,7
230     UNSPILL r0+8, 0
231     TRANSPOSE4x4W 0,1,2,3,5
232     UNSPILL r0, 4,5,6,7
233     SPILL_SHUFFLE r0, 0,1,2,3, 4,5,6,7
234     movq  mm4, m6 ; depends on the permutation to not produce conflicts
235     movq  mm0, m4
236     movq  mm1, m5
237     movq  mm2, mm4
238     movq  mm3, m7
239     INIT_MMX
240     UNSPILL r0+8, 4,5,6,7
241     add   r0, 8
242     call dct8_mmx
243     sub   r0, 8
244     SPILL r0+8, 1,2,3,5,7
245     INIT_MMX
246     UNSPILL r0, 0,1,2,3,4,5,6,7
247     call dct8_mmx
248     SPILL r0, 1,2,3,5,7
249     ret
250
251 INIT_MMX
252 ALIGN 16
253 idct8_mmx:
254     IDCT8_1D 0,1,2,3,4,5,6,7,r1
255     SAVE_MM_PERMUTATION idct8_mmx
256     ret
257
258 %macro ADD_STORE_ROW 3
259     movq  m1, [r0+%1*FDEC_STRIDE]
260     movq  m2, m1
261     punpcklbw m1, m0
262     punpckhbw m2, m0
263     paddw m1, %2
264     paddw m2, %3
265     packuswb m1, m2
266     movq  [r0+%1*FDEC_STRIDE], m1
267 %endmacro
268
269 ;-----------------------------------------------------------------------------
270 ; void x264_add8x8_idct8_mmx( uint8_t *dst, int16_t dct[8][8] )
271 ;-----------------------------------------------------------------------------
272 cglobal x264_add8x8_idct8_mmx, 2,2
273 global x264_add8x8_idct8_mmx %+ .skip_prologue
274 .skip_prologue:
275     INIT_MMX
276     add word [r1], 32
277     UNSPILL r1, 1,2,3,5,6,7
278     call idct8_mmx
279     SPILL r1, 7
280     TRANSPOSE4x4W 0,1,2,3,7
281     SPILL r1, 0,1,2,3
282     UNSPILL r1, 7
283     TRANSPOSE4x4W 4,5,6,7,0
284     SPILL r1, 4,5,6,7
285     INIT_MMX
286     UNSPILL r1+8, 1,2,3,5,6,7
287     add r1, 8
288     call idct8_mmx
289     sub r1, 8
290     SPILL r1+8, 7
291     TRANSPOSE4x4W 0,1,2,3,7
292     SPILL r1+8, 0,1,2,3
293     UNSPILL r1+8, 7
294     TRANSPOSE4x4W 4,5,6,7,0
295     SPILL r1+8, 4,5,6,7
296     INIT_MMX
297     movq  m3, [r1+0x08]
298     movq  m0, [r1+0x40]
299     movq  [r1+0x40], m3
300     movq  [r1+0x08], m0
301     ; memory layout at this time:
302     ; A0------ A1------
303     ; B0------ F0------
304     ; C0------ G0------
305     ; D0------ H0------
306     ; E0------ E1------
307     ; B1------ F1------
308     ; C1------ G1------
309     ; D1------ H1------
310     UNSPILL_SHUFFLE r1, 1,2,3, 5,6,7
311     UNSPILL r1+8, 5,6,7
312     add r1, 8
313     call idct8_mmx
314     sub r1, 8
315     psraw m0, 6
316     psraw m1, 6
317     psraw m2, 6
318     psraw m3, 6
319     psraw m4, 6
320     psraw m5, 6
321     psraw m6, 6
322     psraw m7, 6
323     movq  [r1+0x08], m0 ; mm4
324     movq  [r1+0x48], m4 ; mm5
325     movq  [r1+0x58], m5 ; mm0
326     movq  [r1+0x68], m6 ; mm2
327     movq  [r1+0x78], m7 ; mm6
328     movq  mm5, [r1+0x18]
329     movq  mm6, [r1+0x28]
330     movq  [r1+0x18], m1 ; mm1
331     movq  [r1+0x28], m2 ; mm7
332     movq  mm7, [r1+0x38]
333     movq  [r1+0x38], m3 ; mm3
334     movq  mm1, [r1+0x10]
335     movq  mm2, [r1+0x20]
336     movq  mm3, [r1+0x30]
337     call idct8_mmx
338     psraw m0, 6
339     psraw m1, 6
340     psraw m2, 6
341     psraw m3, 6
342     psraw m4, 6
343     psraw m5, 6
344     psraw m6, 6
345     psraw m7, 6
346     SPILL r1, 0,1,2
347     pxor  m0, m0
348     ADD_STORE_ROW 0, [r1+0x00], [r1+0x08]
349     ADD_STORE_ROW 1, [r1+0x10], [r1+0x18]
350     ADD_STORE_ROW 2, [r1+0x20], [r1+0x28]
351     ADD_STORE_ROW 3, m3, [r1+0x38]
352     ADD_STORE_ROW 4, m4, [r1+0x48]
353     ADD_STORE_ROW 5, m5, [r1+0x58]
354     ADD_STORE_ROW 6, m6, [r1+0x68]
355     ADD_STORE_ROW 7, m7, [r1+0x78]
356     ret
357
358
359
360 INIT_XMM
361
362 ; in: m0..m7, except m6 which is in [%9+0x60]
363 ; out: m0..m7, except m4 which is in [%9+0x40]
364 %macro TRANSPOSE8x8W 9
365     SBUTTERFLY wd, %1, %2, %7
366     movdqa [%9+16], m%2
367     movdqa m%7, [%9+0x60]
368     SBUTTERFLY wd, %3, %4, %2
369     SBUTTERFLY wd, %5, %6, %2
370     SBUTTERFLY wd, %7, %8, %2
371     SBUTTERFLY dq, %1, %3, %2
372     movdqa [%9], m%3
373     movdqa m%2, [%9+16]
374     SBUTTERFLY dq, %2, %4, %3
375     SBUTTERFLY dq, %5, %7, %3
376     SBUTTERFLY dq, %6, %8, %3
377     SBUTTERFLY qdq, %1, %5, %3
378     SBUTTERFLY qdq, %2, %6, %3
379     movdqa [%9+0x40], m%2
380     movdqa m%3, [%9]
381     SBUTTERFLY qdq, %3, %7, %2
382     SBUTTERFLY qdq, %4, %8, %2
383     SWAP %2, %5
384     SWAP %4, %7
385 %endmacro
386
387 ;-----------------------------------------------------------------------------
388 ; void x264_sub8x8_dct8_sse2( int16_t dct[8][8], uint8_t *pix1, uint8_t *pix2 )
389 ;-----------------------------------------------------------------------------
390 cglobal x264_sub8x8_dct8_sse2, 3,3
391 global x264_sub8x8_dct8_sse2 %+ .skip_prologue
392 .skip_prologue:
393     LOAD_DIFF m0, m7, none, [r1+0*FENC_STRIDE], [r2+0*FDEC_STRIDE]
394     LOAD_DIFF m1, m7, none, [r1+1*FENC_STRIDE], [r2+1*FDEC_STRIDE]
395     LOAD_DIFF m2, m7, none, [r1+2*FENC_STRIDE], [r2+2*FDEC_STRIDE]
396     LOAD_DIFF m3, m7, none, [r1+3*FENC_STRIDE], [r2+3*FDEC_STRIDE]
397     LOAD_DIFF m4, m7, none, [r1+4*FENC_STRIDE], [r2+4*FDEC_STRIDE]
398     LOAD_DIFF m5, m7, none, [r1+5*FENC_STRIDE], [r2+5*FDEC_STRIDE]
399     SPILL r0, 0
400     LOAD_DIFF m6, m7, none, [r1+6*FENC_STRIDE], [r2+6*FDEC_STRIDE]
401     LOAD_DIFF m7, m0, none, [r1+7*FENC_STRIDE], [r2+7*FDEC_STRIDE]
402     UNSPILL r0, 0
403     DCT8_1D 0,1,2,3,4,5,6,7,r0
404     UNSPILL r0, 0,4
405     TRANSPOSE8x8W 0,1,2,3,4,5,6,7,r0
406     UNSPILL r0, 4
407     DCT8_1D 0,1,2,3,4,5,6,7,r0
408     SPILL r0, 1,2,3,5,7
409     ret
410
411 ;-----------------------------------------------------------------------------
412 ; void x264_add8x8_idct8_sse2( uint8_t *p_dst, int16_t dct[8][8] )
413 ;-----------------------------------------------------------------------------
414 cglobal x264_add8x8_idct8_sse2, 2,2
415 global x264_add8x8_idct8_sse2 %+ .skip_prologue
416 .skip_prologue:
417     UNSPILL r1, 1,2,3,5,6,7
418     IDCT8_1D   0,1,2,3,4,5,6,7,r1
419     SPILL r1, 6
420     TRANSPOSE8x8W 0,1,2,3,4,5,6,7,r1
421     picgetgot  edx
422     paddw      m0, [pw_32 GLOBAL]
423     SPILL r1, 0
424     IDCT8_1D   0,1,2,3,4,5,6,7,r1
425     SPILL r1, 6,7
426     pxor       m7, m7
427     STORE_DIFF m0, m6, m7, [r0+FDEC_STRIDE*0]
428     STORE_DIFF m1, m6, m7, [r0+FDEC_STRIDE*1]
429     STORE_DIFF m2, m6, m7, [r0+FDEC_STRIDE*2]
430     STORE_DIFF m3, m6, m7, [r0+FDEC_STRIDE*3]
431     STORE_DIFF m4, m6, m7, [r0+FDEC_STRIDE*4]
432     STORE_DIFF m5, m6, m7, [r0+FDEC_STRIDE*5]
433     UNSPILL_SHUFFLE r1, 0,1, 6,7
434     STORE_DIFF m0, m6, m7, [r0+FDEC_STRIDE*6]
435     STORE_DIFF m1, m6, m7, [r0+FDEC_STRIDE*7]
436     ret
437