Merge remote-tracking branch 'qatar/master'
[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 FFmpeg.
6 ;*
7 ;* FFmpeg 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 ;* FFmpeg 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 FFmpeg; 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 "libavutil/x86/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     femms
227     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     emms
252     RET
253
254 INIT_XMM
255 cglobal float_to_fixed24_sse2, 3,3,9, dst, src, len
256     movaps     m0, [pf_1_24]
257 .loop:
258     movaps     m1, [srcq    ]
259     movaps     m2, [srcq+16 ]
260     movaps     m3, [srcq+32 ]
261     movaps     m4, [srcq+48 ]
262 %ifdef m8
263     movaps     m5, [srcq+64 ]
264     movaps     m6, [srcq+80 ]
265     movaps     m7, [srcq+96 ]
266     movaps     m8, [srcq+112]
267 %endif
268     mulps      m1, m0
269     mulps      m2, m0
270     mulps      m3, m0
271     mulps      m4, m0
272 %ifdef m8
273     mulps      m5, m0
274     mulps      m6, m0
275     mulps      m7, m0
276     mulps      m8, m0
277 %endif
278     cvtps2dq   m1, m1
279     cvtps2dq   m2, m2
280     cvtps2dq   m3, m3
281     cvtps2dq   m4, m4
282 %ifdef m8
283     cvtps2dq   m5, m5
284     cvtps2dq   m6, m6
285     cvtps2dq   m7, m7
286     cvtps2dq   m8, m8
287 %endif
288     movdqa  [dstq    ], m1
289     movdqa  [dstq+16 ], m2
290     movdqa  [dstq+32 ], m3
291     movdqa  [dstq+48 ], m4
292 %ifdef m8
293     movdqa  [dstq+64 ], m5
294     movdqa  [dstq+80 ], m6
295     movdqa  [dstq+96 ], m7
296     movdqa  [dstq+112], m8
297     add      srcq, 128
298     add      dstq, 128
299     sub      lenq, 32
300 %else
301     add      srcq, 64
302     add      dstq, 64
303     sub      lenq, 16
304 %endif
305     ja .loop
306     REP_RET
307
308 ;------------------------------------------------------------------------------
309 ; int ff_ac3_compute_mantissa_size(uint16_t mant_cnt[6][16])
310 ;------------------------------------------------------------------------------
311
312 %macro PHADDD4 2 ; xmm src, xmm tmp
313     movhlps  %2, %1
314     paddd    %1, %2
315     pshufd   %2, %1, 0x1
316     paddd    %1, %2
317 %endmacro
318
319 INIT_XMM
320 cglobal ac3_compute_mantissa_size_sse2, 1,2,4, mant_cnt, sum
321     movdqa      m0, [mant_cntq      ]
322     movdqa      m1, [mant_cntq+ 1*16]
323     paddw       m0, [mant_cntq+ 2*16]
324     paddw       m1, [mant_cntq+ 3*16]
325     paddw       m0, [mant_cntq+ 4*16]
326     paddw       m1, [mant_cntq+ 5*16]
327     paddw       m0, [mant_cntq+ 6*16]
328     paddw       m1, [mant_cntq+ 7*16]
329     paddw       m0, [mant_cntq+ 8*16]
330     paddw       m1, [mant_cntq+ 9*16]
331     paddw       m0, [mant_cntq+10*16]
332     paddw       m1, [mant_cntq+11*16]
333     pmaddwd     m0, [ac3_bap_bits   ]
334     pmaddwd     m1, [ac3_bap_bits+16]
335     paddd       m0, m1
336     PHADDD4     m0, m1
337     movd      sumd, m0
338     movdqa      m3, [pw_bap_mul1]
339     movhpd      m0, [mant_cntq     +2]
340     movlpd      m0, [mant_cntq+1*32+2]
341     movhpd      m1, [mant_cntq+2*32+2]
342     movlpd      m1, [mant_cntq+3*32+2]
343     movhpd      m2, [mant_cntq+4*32+2]
344     movlpd      m2, [mant_cntq+5*32+2]
345     pmulhuw     m0, m3
346     pmulhuw     m1, m3
347     pmulhuw     m2, m3
348     paddusw     m0, m1
349     paddusw     m0, m2
350     pmaddwd     m0, [pw_bap_mul2]
351     PHADDD4     m0, m1
352     movd       eax, m0
353     add        eax, sumd
354     RET
355
356 ;------------------------------------------------------------------------------
357 ; void ff_ac3_extract_exponents(uint8_t *exp, int32_t *coef, int nb_coefs)
358 ;------------------------------------------------------------------------------
359
360 %macro PABSD_MMX 2 ; src/dst, tmp
361     pxor     %2, %2
362     pcmpgtd  %2, %1
363     pxor     %1, %2
364     psubd    %1, %2
365 %endmacro
366
367 %macro PABSD_SSSE3 1-2 ; src/dst, unused
368     pabsd    %1, %1
369 %endmacro
370
371 %if HAVE_AMD3DNOW
372 INIT_MMX
373 cglobal ac3_extract_exponents_3dnow, 3,3,0, exp, coef, len
374     add      expq, lenq
375     lea     coefq, [coefq+4*lenq]
376     neg      lenq
377     movq       m3, [pd_1]
378     movq       m4, [pd_151]
379 .loop:
380     movq       m0, [coefq+4*lenq  ]
381     movq       m1, [coefq+4*lenq+8]
382     PABSD_MMX  m0, m2
383     PABSD_MMX  m1, m2
384     pslld      m0, 1
385     por        m0, m3
386     pi2fd      m2, m0
387     psrld      m2, 23
388     movq       m0, m4
389     psubd      m0, m2
390     pslld      m1, 1
391     por        m1, m3
392     pi2fd      m2, m1
393     psrld      m2, 23
394     movq       m1, m4
395     psubd      m1, m2
396     packssdw   m0, m0
397     packuswb   m0, m0
398     packssdw   m1, m1
399     packuswb   m1, m1
400     punpcklwd  m0, m1
401     movd  [expq+lenq], m0
402     add      lenq, 4
403     jl .loop
404     REP_RET
405 %endif
406
407 %macro AC3_EXTRACT_EXPONENTS 1
408 cglobal ac3_extract_exponents_%1, 3,3,4, exp, coef, len
409     add     expq, lenq
410     lea    coefq, [coefq+4*lenq]
411     neg     lenq
412     mova      m2, [pd_1]
413     mova      m3, [pd_151]
414 .loop:
415     ; move 4 32-bit coefs to xmm0
416     mova      m0, [coefq+4*lenq]
417     ; absolute value
418     PABSD     m0, m1
419     ; convert to float and extract exponents
420     pslld     m0, 1
421     por       m0, m2
422     cvtdq2ps  m1, m0
423     psrld     m1, 23
424     mova      m0, m3
425     psubd     m0, m1
426     ; move the lowest byte in each of 4 dwords to the low dword
427     ; NOTE: We cannot just extract the low bytes with pshufb because the dword
428     ;       result for 16777215 is -1 due to float inaccuracy. Using packuswb
429     ;       clips this to 0, which is the correct exponent.
430     packssdw  m0, m0
431     packuswb  m0, m0
432     movd  [expq+lenq], m0
433
434     add     lenq, 4
435     jl .loop
436     REP_RET
437 %endmacro
438
439 %if HAVE_SSE
440 INIT_XMM
441 %define PABSD PABSD_MMX
442 AC3_EXTRACT_EXPONENTS sse2
443 %if HAVE_SSSE3
444 %define PABSD PABSD_SSSE3
445 AC3_EXTRACT_EXPONENTS ssse3
446 %endif
447 %endif