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