]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/ac3dsp.asm
x86: conditionally compile H.264 QPEL optimizations
[ffmpeg] / libavcodec / x86 / ac3dsp.asm
1 ;*****************************************************************************
2 ;* x86-optimized AC-3 DSP utils
3 ;* Copyright (c) 2011 Justin Ruggles
4 ;*
5 ;* This file is part of Libav.
6 ;*
7 ;* Libav is free software; you can redistribute it and/or
8 ;* modify it under the terms of the GNU Lesser General Public
9 ;* License as published by the Free Software Foundation; either
10 ;* version 2.1 of the License, or (at your option) any later version.
11 ;*
12 ;* Libav is distributed in the hope that it will be useful,
13 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;* Lesser General Public License for more details.
16 ;*
17 ;* You should have received a copy of the GNU Lesser General Public
18 ;* License along with Libav; if not, write to the Free Software
19 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ;******************************************************************************
21
22 %include "x86inc.asm"
23 %include "x86util.asm"
24
25 SECTION_RODATA
26
27 ; 16777216.0f - used in ff_float_to_fixed24()
28 pf_1_24: times 4 dd 0x4B800000
29
30 ; used in ff_ac3_compute_mantissa_size()
31 cextern ac3_bap_bits
32 pw_bap_mul1: dw 21846, 21846, 0, 32768, 21846, 21846, 0, 32768
33 pw_bap_mul2: dw 5, 7, 0, 7, 5, 7, 0, 7
34
35 ; used in ff_ac3_extract_exponents()
36 pd_1:   times 4 dd 1
37 pd_151: times 4 dd 151
38
39 SECTION .text
40
41 ;-----------------------------------------------------------------------------
42 ; void ff_ac3_exponent_min(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
43 ;-----------------------------------------------------------------------------
44
45 %macro AC3_EXPONENT_MIN 1
46 cglobal ac3_exponent_min_%1, 3,4,2, exp, reuse_blks, expn, offset
47     shl  reuse_blksq, 8
48     jz .end
49     LOOP_ALIGN
50 .nextexp:
51     mov      offsetq, reuse_blksq
52     mova          m0, [expq+offsetq]
53     sub      offsetq, 256
54     LOOP_ALIGN
55 .nextblk:
56     PMINUB        m0, [expq+offsetq], m1
57     sub      offsetq, 256
58     jae .nextblk
59     mova      [expq], m0
60     add         expq, mmsize
61     sub        expnq, mmsize
62     jg .nextexp
63 .end:
64     REP_RET
65 %endmacro
66
67 %define PMINUB PMINUB_MMX
68 %define LOOP_ALIGN
69 INIT_MMX
70 AC3_EXPONENT_MIN mmx
71 %if HAVE_MMX2
72 %define PMINUB PMINUB_MMXEXT
73 %define LOOP_ALIGN ALIGN 16
74 AC3_EXPONENT_MIN mmxext
75 %endif
76 %if HAVE_SSE
77 INIT_XMM
78 AC3_EXPONENT_MIN sse2
79 %endif
80 %undef PMINUB
81 %undef LOOP_ALIGN
82
83 ;-----------------------------------------------------------------------------
84 ; int ff_ac3_max_msb_abs_int16(const int16_t *src, int len)
85 ;
86 ; This function uses 2 different methods to calculate a valid result.
87 ; 1) logical 'or' of abs of each element
88 ;        This is used for ssse3 because of the pabsw instruction.
89 ;        It is also used for mmx because of the lack of min/max instructions.
90 ; 2) calculate min/max for the array, then or(abs(min),abs(max))
91 ;        This is used for mmxext and sse2 because they have pminsw/pmaxsw.
92 ;-----------------------------------------------------------------------------
93
94 %macro AC3_MAX_MSB_ABS_INT16 2
95 cglobal ac3_max_msb_abs_int16_%1, 2,2,5, src, len
96     pxor        m2, m2
97     pxor        m3, m3
98 .loop:
99 %ifidn %2, min_max
100     mova        m0, [srcq]
101     mova        m1, [srcq+mmsize]
102     pminsw      m2, m0
103     pminsw      m2, m1
104     pmaxsw      m3, m0
105     pmaxsw      m3, m1
106 %else ; or_abs
107 %ifidn %1, mmx
108     mova        m0, [srcq]
109     mova        m1, [srcq+mmsize]
110     ABS2        m0, m1, m3, m4
111 %else ; ssse3
112     ; using memory args is faster for ssse3
113     pabsw       m0, [srcq]
114     pabsw       m1, [srcq+mmsize]
115 %endif
116     por         m2, m0
117     por         m2, m1
118 %endif
119     add       srcq, mmsize*2
120     sub       lend, mmsize
121     ja .loop
122 %ifidn %2, min_max
123     ABS2        m2, m3, m0, m1
124     por         m2, m3
125 %endif
126 %ifidn mmsize, 16
127     movhlps     m0, m2
128     por         m2, m0
129 %endif
130     PSHUFLW     m0, m2, 0xe
131     por         m2, m0
132     PSHUFLW     m0, m2, 0x1
133     por         m2, m0
134     movd       eax, m2
135     and        eax, 0xFFFF
136     RET
137 %endmacro
138
139 INIT_MMX
140 %define ABS2 ABS2_MMX
141 %define PSHUFLW pshufw
142 AC3_MAX_MSB_ABS_INT16 mmx, or_abs
143 %define ABS2 ABS2_MMX2
144 AC3_MAX_MSB_ABS_INT16 mmxext, min_max
145 INIT_XMM
146 %define PSHUFLW pshuflw
147 AC3_MAX_MSB_ABS_INT16 sse2, min_max
148 %define ABS2 ABS2_SSSE3
149 AC3_MAX_MSB_ABS_INT16 ssse3, or_abs
150
151 ;-----------------------------------------------------------------------------
152 ; macro used for ff_ac3_lshift_int16() and ff_ac3_rshift_int32()
153 ;-----------------------------------------------------------------------------
154
155 %macro AC3_SHIFT 4 ; l/r, 16/32, shift instruction, instruction set
156 cglobal ac3_%1shift_int%2_%4, 3,3,5, src, len, shift
157     movd      m0, shiftd
158 .loop:
159     mova      m1, [srcq         ]
160     mova      m2, [srcq+mmsize  ]
161     mova      m3, [srcq+mmsize*2]
162     mova      m4, [srcq+mmsize*3]
163     %3        m1, m0
164     %3        m2, m0
165     %3        m3, m0
166     %3        m4, m0
167     mova  [srcq         ], m1
168     mova  [srcq+mmsize  ], m2
169     mova  [srcq+mmsize*2], m3
170     mova  [srcq+mmsize*3], m4
171     add     srcq, mmsize*4
172     sub     lend, mmsize*32/%2
173     ja .loop
174 .end:
175     REP_RET
176 %endmacro
177
178 ;-----------------------------------------------------------------------------
179 ; void ff_ac3_lshift_int16(int16_t *src, unsigned int len, unsigned int shift)
180 ;-----------------------------------------------------------------------------
181
182 INIT_MMX
183 AC3_SHIFT l, 16, psllw, mmx
184 INIT_XMM
185 AC3_SHIFT l, 16, psllw, sse2
186
187 ;-----------------------------------------------------------------------------
188 ; void ff_ac3_rshift_int32(int32_t *src, unsigned int len, unsigned int shift)
189 ;-----------------------------------------------------------------------------
190
191 INIT_MMX
192 AC3_SHIFT r, 32, psrad, mmx
193 INIT_XMM
194 AC3_SHIFT r, 32, psrad, sse2
195
196 ;-----------------------------------------------------------------------------
197 ; void ff_float_to_fixed24(int32_t *dst, const float *src, unsigned int len)
198 ;-----------------------------------------------------------------------------
199
200 ; The 3DNow! version is not bit-identical because pf2id uses truncation rather
201 ; than round-to-nearest.
202 INIT_MMX
203 cglobal float_to_fixed24_3dnow, 3,3,0, dst, src, len
204     movq   m0, [pf_1_24]
205 .loop:
206     movq   m1, [srcq   ]
207     movq   m2, [srcq+8 ]
208     movq   m3, [srcq+16]
209     movq   m4, [srcq+24]
210     pfmul  m1, m0
211     pfmul  m2, m0
212     pfmul  m3, m0
213     pfmul  m4, m0
214     pf2id  m1, m1
215     pf2id  m2, m2
216     pf2id  m3, m3
217     pf2id  m4, m4
218     movq  [dstq   ], m1
219     movq  [dstq+8 ], m2
220     movq  [dstq+16], m3
221     movq  [dstq+24], m4
222     add  srcq, 32
223     add  dstq, 32
224     sub  lend, 8
225     ja .loop
226     REP_RET
227
228 INIT_XMM
229 cglobal float_to_fixed24_sse, 3,3,3, dst, src, len
230     movaps     m0, [pf_1_24]
231 .loop:
232     movaps     m1, [srcq   ]
233     movaps     m2, [srcq+16]
234     mulps      m1, m0
235     mulps      m2, m0
236     cvtps2pi  mm0, m1
237     movhlps    m1, m1
238     cvtps2pi  mm1, m1
239     cvtps2pi  mm2, m2
240     movhlps    m2, m2
241     cvtps2pi  mm3, m2
242     movq  [dstq   ], mm0
243     movq  [dstq+ 8], mm1
244     movq  [dstq+16], mm2
245     movq  [dstq+24], mm3
246     add      srcq, 32
247     add      dstq, 32
248     sub      lend, 8
249     ja .loop
250     REP_RET
251
252 INIT_XMM
253 cglobal float_to_fixed24_sse2, 3,3,9, dst, src, len
254     movaps     m0, [pf_1_24]
255 .loop:
256     movaps     m1, [srcq    ]
257     movaps     m2, [srcq+16 ]
258     movaps     m3, [srcq+32 ]
259     movaps     m4, [srcq+48 ]
260 %ifdef m8
261     movaps     m5, [srcq+64 ]
262     movaps     m6, [srcq+80 ]
263     movaps     m7, [srcq+96 ]
264     movaps     m8, [srcq+112]
265 %endif
266     mulps      m1, m0
267     mulps      m2, m0
268     mulps      m3, m0
269     mulps      m4, m0
270 %ifdef m8
271     mulps      m5, m0
272     mulps      m6, m0
273     mulps      m7, m0
274     mulps      m8, m0
275 %endif
276     cvtps2dq   m1, m1
277     cvtps2dq   m2, m2
278     cvtps2dq   m3, m3
279     cvtps2dq   m4, m4
280 %ifdef m8
281     cvtps2dq   m5, m5
282     cvtps2dq   m6, m6
283     cvtps2dq   m7, m7
284     cvtps2dq   m8, m8
285 %endif
286     movdqa  [dstq    ], m1
287     movdqa  [dstq+16 ], m2
288     movdqa  [dstq+32 ], m3
289     movdqa  [dstq+48 ], m4
290 %ifdef m8
291     movdqa  [dstq+64 ], m5
292     movdqa  [dstq+80 ], m6
293     movdqa  [dstq+96 ], m7
294     movdqa  [dstq+112], m8
295     add      srcq, 128
296     add      dstq, 128
297     sub      lenq, 32
298 %else
299     add      srcq, 64
300     add      dstq, 64
301     sub      lenq, 16
302 %endif
303     ja .loop
304     REP_RET
305
306 ;------------------------------------------------------------------------------
307 ; int ff_ac3_compute_mantissa_size(uint16_t mant_cnt[6][16])
308 ;------------------------------------------------------------------------------
309
310 %macro PHADDD4 2 ; xmm src, xmm tmp
311     movhlps  %2, %1
312     paddd    %1, %2
313     pshufd   %2, %1, 0x1
314     paddd    %1, %2
315 %endmacro
316
317 INIT_XMM
318 cglobal ac3_compute_mantissa_size_sse2, 1,2,4, mant_cnt, sum
319     movdqa      m0, [mant_cntq      ]
320     movdqa      m1, [mant_cntq+ 1*16]
321     paddw       m0, [mant_cntq+ 2*16]
322     paddw       m1, [mant_cntq+ 3*16]
323     paddw       m0, [mant_cntq+ 4*16]
324     paddw       m1, [mant_cntq+ 5*16]
325     paddw       m0, [mant_cntq+ 6*16]
326     paddw       m1, [mant_cntq+ 7*16]
327     paddw       m0, [mant_cntq+ 8*16]
328     paddw       m1, [mant_cntq+ 9*16]
329     paddw       m0, [mant_cntq+10*16]
330     paddw       m1, [mant_cntq+11*16]
331     pmaddwd     m0, [ac3_bap_bits   ]
332     pmaddwd     m1, [ac3_bap_bits+16]
333     paddd       m0, m1
334     PHADDD4     m0, m1
335     movd      sumd, m0
336     movdqa      m3, [pw_bap_mul1]
337     movhpd      m0, [mant_cntq     +2]
338     movlpd      m0, [mant_cntq+1*32+2]
339     movhpd      m1, [mant_cntq+2*32+2]
340     movlpd      m1, [mant_cntq+3*32+2]
341     movhpd      m2, [mant_cntq+4*32+2]
342     movlpd      m2, [mant_cntq+5*32+2]
343     pmulhuw     m0, m3
344     pmulhuw     m1, m3
345     pmulhuw     m2, m3
346     paddusw     m0, m1
347     paddusw     m0, m2
348     pmaddwd     m0, [pw_bap_mul2]
349     PHADDD4     m0, m1
350     movd       eax, m0
351     add        eax, sumd
352     RET
353
354 ;------------------------------------------------------------------------------
355 ; void ff_ac3_extract_exponents(uint8_t *exp, int32_t *coef, int nb_coefs)
356 ;------------------------------------------------------------------------------
357
358 %macro PABSD_MMX 2 ; src/dst, tmp
359     pxor     %2, %2
360     pcmpgtd  %2, %1
361     pxor     %1, %2
362     psubd    %1, %2
363 %endmacro
364
365 %macro PABSD_SSSE3 1-2 ; src/dst, unused
366     pabsd    %1, %1
367 %endmacro
368
369 %if HAVE_AMD3DNOW
370 INIT_MMX
371 cglobal ac3_extract_exponents_3dnow, 3,3,0, exp, coef, len
372     add      expq, lenq
373     lea     coefq, [coefq+4*lenq]
374     neg      lenq
375     movq       m3, [pd_1]
376     movq       m4, [pd_151]
377 .loop:
378     movq       m0, [coefq+4*lenq  ]
379     movq       m1, [coefq+4*lenq+8]
380     PABSD_MMX  m0, m2
381     PABSD_MMX  m1, m2
382     pslld      m0, 1
383     por        m0, m3
384     pi2fd      m2, m0
385     psrld      m2, 23
386     movq       m0, m4
387     psubd      m0, m2
388     pslld      m1, 1
389     por        m1, m3
390     pi2fd      m2, m1
391     psrld      m2, 23
392     movq       m1, m4
393     psubd      m1, m2
394     packssdw   m0, m0
395     packuswb   m0, m0
396     packssdw   m1, m1
397     packuswb   m1, m1
398     punpcklwd  m0, m1
399     movd  [expq+lenq], m0
400     add      lenq, 4
401     jl .loop
402     REP_RET
403 %endif
404
405 %macro AC3_EXTRACT_EXPONENTS 1
406 cglobal ac3_extract_exponents_%1, 3,3,4, exp, coef, len
407     add     expq, lenq
408     lea    coefq, [coefq+4*lenq]
409     neg     lenq
410     mova      m2, [pd_1]
411     mova      m3, [pd_151]
412 .loop:
413     ; move 4 32-bit coefs to xmm0
414     mova      m0, [coefq+4*lenq]
415     ; absolute value
416     PABSD     m0, m1
417     ; convert to float and extract exponents
418     pslld     m0, 1
419     por       m0, m2
420     cvtdq2ps  m1, m0
421     psrld     m1, 23
422     mova      m0, m3
423     psubd     m0, m1
424     ; move the lowest byte in each of 4 dwords to the low dword
425     ; NOTE: We cannot just extract the low bytes with pshufb because the dword
426     ;       result for 16777215 is -1 due to float inaccuracy. Using packuswb
427     ;       clips this to 0, which is the correct exponent.
428     packssdw  m0, m0
429     packuswb  m0, m0
430     movd  [expq+lenq], m0
431
432     add     lenq, 4
433     jl .loop
434     REP_RET
435 %endmacro
436
437 %if HAVE_SSE
438 INIT_XMM
439 %define PABSD PABSD_MMX
440 AC3_EXTRACT_EXPONENTS sse2
441 %if HAVE_SSSE3
442 %define PABSD PABSD_SSSE3
443 AC3_EXTRACT_EXPONENTS ssse3
444 %endif
445 %endif