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