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