]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/ac3dsp.asm
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / 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 "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 SECTION .text
36
37 ;-----------------------------------------------------------------------------
38 ; void ff_ac3_exponent_min(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
39 ;-----------------------------------------------------------------------------
40
41 %macro AC3_EXPONENT_MIN 1
42 cglobal ac3_exponent_min_%1, 3,4,2, exp, reuse_blks, expn, offset
43     shl  reuse_blksq, 8
44     jz .end
45     LOOP_ALIGN
46 .nextexp:
47     mov      offsetq, reuse_blksq
48     mova          m0, [expq+offsetq]
49     sub      offsetq, 256
50     LOOP_ALIGN
51 .nextblk:
52     PMINUB        m0, [expq+offsetq], m1
53     sub      offsetq, 256
54     jae .nextblk
55     mova      [expq], m0
56     add         expq, mmsize
57     sub        expnq, mmsize
58     jg .nextexp
59 .end:
60     REP_RET
61 %endmacro
62
63 %define PMINUB PMINUB_MMX
64 %define LOOP_ALIGN
65 INIT_MMX
66 AC3_EXPONENT_MIN mmx
67 %ifdef HAVE_MMX2
68 %define PMINUB PMINUB_MMXEXT
69 %define LOOP_ALIGN ALIGN 16
70 AC3_EXPONENT_MIN mmxext
71 %endif
72 %ifdef HAVE_SSE
73 INIT_XMM
74 AC3_EXPONENT_MIN sse2
75 %endif
76 %undef PMINUB
77 %undef LOOP_ALIGN
78
79 ;-----------------------------------------------------------------------------
80 ; int ff_ac3_max_msb_abs_int16(const int16_t *src, int len)
81 ;
82 ; This function uses 2 different methods to calculate a valid result.
83 ; 1) logical 'or' of abs of each element
84 ;        This is used for ssse3 because of the pabsw instruction.
85 ;        It is also used for mmx because of the lack of min/max instructions.
86 ; 2) calculate min/max for the array, then or(abs(min),abs(max))
87 ;        This is used for mmxext and sse2 because they have pminsw/pmaxsw.
88 ;-----------------------------------------------------------------------------
89
90 %macro AC3_MAX_MSB_ABS_INT16 2
91 cglobal ac3_max_msb_abs_int16_%1, 2,2,5, src, len
92     pxor        m2, m2
93     pxor        m3, m3
94 .loop:
95 %ifidn %2, min_max
96     mova        m0, [srcq]
97     mova        m1, [srcq+mmsize]
98     pminsw      m2, m0
99     pminsw      m2, m1
100     pmaxsw      m3, m0
101     pmaxsw      m3, m1
102 %else ; or_abs
103 %ifidn %1, mmx
104     mova        m0, [srcq]
105     mova        m1, [srcq+mmsize]
106     ABS2        m0, m1, m3, m4
107 %else ; ssse3
108     ; using memory args is faster for ssse3
109     pabsw       m0, [srcq]
110     pabsw       m1, [srcq+mmsize]
111 %endif
112     por         m2, m0
113     por         m2, m1
114 %endif
115     add       srcq, mmsize*2
116     sub       lend, mmsize
117     ja .loop
118 %ifidn %2, min_max
119     ABS2        m2, m3, m0, m1
120     por         m2, m3
121 %endif
122 %ifidn mmsize, 16
123     movhlps     m0, m2
124     por         m2, m0
125 %endif
126     PSHUFLW     m0, m2, 0xe
127     por         m2, m0
128     PSHUFLW     m0, m2, 0x1
129     por         m2, m0
130     movd       eax, m2
131     and        eax, 0xFFFF
132     RET
133 %endmacro
134
135 INIT_MMX
136 %define ABS2 ABS2_MMX
137 %define PSHUFLW pshufw
138 AC3_MAX_MSB_ABS_INT16 mmx, or_abs
139 %define ABS2 ABS2_MMX2
140 AC3_MAX_MSB_ABS_INT16 mmxext, min_max
141 INIT_XMM
142 %define PSHUFLW pshuflw
143 AC3_MAX_MSB_ABS_INT16 sse2, min_max
144 %define ABS2 ABS2_SSSE3
145 AC3_MAX_MSB_ABS_INT16 ssse3, or_abs
146
147 ;-----------------------------------------------------------------------------
148 ; macro used for ff_ac3_lshift_int16() and ff_ac3_rshift_int32()
149 ;-----------------------------------------------------------------------------
150
151 %macro AC3_SHIFT 4 ; l/r, 16/32, shift instruction, instruction set
152 cglobal ac3_%1shift_int%2_%4, 3,3,5, src, len, shift
153     movd      m0, shiftd
154 .loop:
155     mova      m1, [srcq         ]
156     mova      m2, [srcq+mmsize  ]
157     mova      m3, [srcq+mmsize*2]
158     mova      m4, [srcq+mmsize*3]
159     %3        m1, m0
160     %3        m2, m0
161     %3        m3, m0
162     %3        m4, m0
163     mova  [srcq         ], m1
164     mova  [srcq+mmsize  ], m2
165     mova  [srcq+mmsize*2], m3
166     mova  [srcq+mmsize*3], m4
167     add     srcq, mmsize*4
168     sub     lend, mmsize*32/%2
169     ja .loop
170 .end:
171     REP_RET
172 %endmacro
173
174 ;-----------------------------------------------------------------------------
175 ; void ff_ac3_lshift_int16(int16_t *src, unsigned int len, unsigned int shift)
176 ;-----------------------------------------------------------------------------
177
178 INIT_MMX
179 AC3_SHIFT l, 16, psllw, mmx
180 INIT_XMM
181 AC3_SHIFT l, 16, psllw, sse2
182
183 ;-----------------------------------------------------------------------------
184 ; void ff_ac3_rshift_int32(int32_t *src, unsigned int len, unsigned int shift)
185 ;-----------------------------------------------------------------------------
186
187 INIT_MMX
188 AC3_SHIFT r, 32, psrad, mmx
189 INIT_XMM
190 AC3_SHIFT r, 32, psrad, sse2
191
192 ;-----------------------------------------------------------------------------
193 ; void ff_float_to_fixed24(int32_t *dst, const float *src, unsigned int len)
194 ;-----------------------------------------------------------------------------
195
196 ; The 3DNow! version is not bit-identical because pf2id uses truncation rather
197 ; than round-to-nearest.
198 INIT_MMX
199 cglobal float_to_fixed24_3dnow, 3,3,0, dst, src, len
200     movq   m0, [pf_1_24]
201 .loop:
202     movq   m1, [srcq   ]
203     movq   m2, [srcq+8 ]
204     movq   m3, [srcq+16]
205     movq   m4, [srcq+24]
206     pfmul  m1, m0
207     pfmul  m2, m0
208     pfmul  m3, m0
209     pfmul  m4, m0
210     pf2id  m1, m1
211     pf2id  m2, m2
212     pf2id  m3, m3
213     pf2id  m4, m4
214     movq  [dstq   ], m1
215     movq  [dstq+8 ], m2
216     movq  [dstq+16], m3
217     movq  [dstq+24], m4
218     add  srcq, 32
219     add  dstq, 32
220     sub  lend, 8
221     ja .loop
222     REP_RET
223
224 INIT_XMM
225 cglobal float_to_fixed24_sse, 3,3,3, dst, src, len
226     movaps     m0, [pf_1_24]
227 .loop:
228     movaps     m1, [srcq   ]
229     movaps     m2, [srcq+16]
230     mulps      m1, m0
231     mulps      m2, m0
232     cvtps2pi  mm0, m1
233     movhlps    m1, m1
234     cvtps2pi  mm1, m1
235     cvtps2pi  mm2, m2
236     movhlps    m2, m2
237     cvtps2pi  mm3, m2
238     movq  [dstq   ], mm0
239     movq  [dstq+ 8], mm1
240     movq  [dstq+16], mm2
241     movq  [dstq+24], mm3
242     add      srcq, 32
243     add      dstq, 32
244     sub      lend, 8
245     ja .loop
246     REP_RET
247
248 INIT_XMM
249 cglobal float_to_fixed24_sse2, 3,3,9, dst, src, len
250     movaps     m0, [pf_1_24]
251 .loop:
252     movaps     m1, [srcq    ]
253     movaps     m2, [srcq+16 ]
254     movaps     m3, [srcq+32 ]
255     movaps     m4, [srcq+48 ]
256 %ifdef m8
257     movaps     m5, [srcq+64 ]
258     movaps     m6, [srcq+80 ]
259     movaps     m7, [srcq+96 ]
260     movaps     m8, [srcq+112]
261 %endif
262     mulps      m1, m0
263     mulps      m2, m0
264     mulps      m3, m0
265     mulps      m4, m0
266 %ifdef m8
267     mulps      m5, m0
268     mulps      m6, m0
269     mulps      m7, m0
270     mulps      m8, m0
271 %endif
272     cvtps2dq   m1, m1
273     cvtps2dq   m2, m2
274     cvtps2dq   m3, m3
275     cvtps2dq   m4, m4
276 %ifdef m8
277     cvtps2dq   m5, m5
278     cvtps2dq   m6, m6
279     cvtps2dq   m7, m7
280     cvtps2dq   m8, m8
281 %endif
282     movdqa  [dstq    ], m1
283     movdqa  [dstq+16 ], m2
284     movdqa  [dstq+32 ], m3
285     movdqa  [dstq+48 ], m4
286 %ifdef m8
287     movdqa  [dstq+64 ], m5
288     movdqa  [dstq+80 ], m6
289     movdqa  [dstq+96 ], m7
290     movdqa  [dstq+112], m8
291     add      srcq, 128
292     add      dstq, 128
293     sub      lenq, 32
294 %else
295     add      srcq, 64
296     add      dstq, 64
297     sub      lenq, 16
298 %endif
299     ja .loop
300     REP_RET
301
302 ;------------------------------------------------------------------------------
303 ; int ff_ac3_compute_mantissa_size(uint16_t mant_cnt[6][16])
304 ;------------------------------------------------------------------------------
305
306 %macro PHADDD4 2 ; xmm src, xmm tmp
307     movhlps  %2, %1
308     paddd    %1, %2
309     pshufd   %2, %1, 0x1
310     paddd    %1, %2
311 %endmacro
312
313 INIT_XMM
314 cglobal ac3_compute_mantissa_size_sse2, 1,2,4, mant_cnt, sum
315     movdqa      m0, [mant_cntq      ]
316     movdqa      m1, [mant_cntq+ 1*16]
317     paddw       m0, [mant_cntq+ 2*16]
318     paddw       m1, [mant_cntq+ 3*16]
319     paddw       m0, [mant_cntq+ 4*16]
320     paddw       m1, [mant_cntq+ 5*16]
321     paddw       m0, [mant_cntq+ 6*16]
322     paddw       m1, [mant_cntq+ 7*16]
323     paddw       m0, [mant_cntq+ 8*16]
324     paddw       m1, [mant_cntq+ 9*16]
325     paddw       m0, [mant_cntq+10*16]
326     paddw       m1, [mant_cntq+11*16]
327     pmaddwd     m0, [ac3_bap_bits   ]
328     pmaddwd     m1, [ac3_bap_bits+16]
329     paddd       m0, m1
330     PHADDD4     m0, m1
331     movd      sumd, m0
332     movdqa      m3, [pw_bap_mul1]
333     movhpd      m0, [mant_cntq     +2]
334     movlpd      m0, [mant_cntq+1*32+2]
335     movhpd      m1, [mant_cntq+2*32+2]
336     movlpd      m1, [mant_cntq+3*32+2]
337     movhpd      m2, [mant_cntq+4*32+2]
338     movlpd      m2, [mant_cntq+5*32+2]
339     pmulhuw     m0, m3
340     pmulhuw     m1, m3
341     pmulhuw     m2, m3
342     paddusw     m0, m1
343     paddusw     m0, m2
344     pmaddwd     m0, [pw_bap_mul2]
345     PHADDD4     m0, m1
346     movd       eax, m0
347     add        eax, sumd
348     RET