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