update copyright date to include 2002
[flac.git] / src / libFLAC / ia32 / lpc_asm.nasm
1 ; libFLAC - Free Lossless Audio Codec library
2 ; Copyright (C) 2001,2002  Josh Coalson
3 ;
4 ; This library is free software; you can redistribute it and/or
5 ; modify it under the terms of the GNU Library General Public
6 ; License as published by the Free Software Foundation; either
7 ; version 2 of the License, or (at your option) any later version.
8 ;
9 ; This library is distributed in the hope that it will be useful,
10 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 ; Library General Public License for more details.
13 ;
14 ; You should have received a copy of the GNU Library General Public
15 ; License along with this library; if not, write to the
16 ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 ; Boston, MA  02111-1307, USA.
18
19 %include "nasm.h"
20
21         data_section
22
23 cglobal FLAC__lpc_compute_autocorrelation_asm_ia32
24 cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4
25 cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8
26 cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12
27 cglobal FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow
28 cglobal FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32
29 cglobal FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx
30 cglobal FLAC__lpc_restore_signal_asm_ia32
31 cglobal FLAC__lpc_restore_signal_asm_ia32_mmx
32
33         code_section
34
35 ; **********************************************************************
36 ;
37 ; void FLAC__lpc_compute_autocorrelation_asm(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[])
38 ; {
39 ;       FLAC__real d;
40 ;       unsigned sample, coeff;
41 ;       const unsigned limit = data_len - lag;
42 ;
43 ;       FLAC__ASSERT(lag > 0);
44 ;       FLAC__ASSERT(lag <= data_len);
45 ;
46 ;       for(coeff = 0; coeff < lag; coeff++)
47 ;               autoc[coeff] = 0.0;
48 ;       for(sample = 0; sample <= limit; sample++) {
49 ;               d = data[sample];
50 ;               for(coeff = 0; coeff < lag; coeff++)
51 ;                       autoc[coeff] += d * data[sample+coeff];
52 ;       }
53 ;       for(; sample < data_len; sample++) {
54 ;               d = data[sample];
55 ;               for(coeff = 0; coeff < data_len - sample; coeff++)
56 ;                       autoc[coeff] += d * data[sample+coeff];
57 ;       }
58 ; }
59 ;
60         ALIGN 16
61 cident FLAC__lpc_compute_autocorrelation_asm_ia32
62         ;[esp + 28] == autoc[]
63         ;[esp + 24] == lag
64         ;[esp + 20] == data_len
65         ;[esp + 16] == data[]
66
67         ;ASSERT(lag > 0)
68         ;ASSERT(lag <= 33)
69         ;ASSERT(lag <= data_len)
70
71 .begin:
72         push    esi
73         push    edi
74         push    ebx
75
76         ;       for(coeff = 0; coeff < lag; coeff++)
77         ;               autoc[coeff] = 0.0;
78         mov     edi, [esp + 28]                 ; edi == autoc
79         mov     ecx, [esp + 24]                 ; ecx = # of dwords (=lag) of 0 to write
80         xor     eax, eax
81         rep     stosd
82
83         ;       const unsigned limit = data_len - lag;
84         mov     eax, [esp + 24]                 ; eax == lag
85         mov     ecx, [esp + 20]
86         sub     ecx, eax                        ; ecx == limit
87
88         mov     edi, [esp + 28]                 ; edi == autoc
89         mov     esi, [esp + 16]                 ; esi == data
90         inc     ecx                             ; we are looping <= limit so we add one to the counter
91
92         ;       for(sample = 0; sample <= limit; sample++) {
93         ;               d = data[sample];
94         ;               for(coeff = 0; coeff < lag; coeff++)
95         ;                       autoc[coeff] += d * data[sample+coeff];
96         ;       }
97         fld     dword [esi]                     ; ST = d <- data[sample]
98         ; each iteration is 11 bytes so we need (-eax)*11, so we do (-12*eax + eax)
99         lea     edx, [eax + eax*2]
100         neg     edx
101         lea     edx, [eax + edx*4 + .jumper1_0 - .get_eip1]
102         call    .get_eip1
103 .get_eip1:
104         pop     ebx
105         add     edx, ebx
106         inc     edx                             ; compensate for the shorter opcode on the last iteration
107         inc     edx                             ; compensate for the shorter opcode on the last iteration
108         inc     edx                             ; compensate for the shorter opcode on the last iteration
109         cmp     eax, 33
110         jne     .loop1_start
111         sub     edx, byte 9                     ; compensate for the longer opcodes on the first iteration
112 .loop1_start:
113         jmp     edx
114
115         fld     st0                             ; ST = d d
116         fmul    dword [esi + (32*4)]            ; ST = d*data[sample+32] d              WATCHOUT: not a byte displacement here!
117         fadd    dword [edi + (32*4)]            ; ST = autoc[32]+d*data[sample+32] d    WATCHOUT: not a byte displacement here!
118         fstp    dword [edi + (32*4)]            ; autoc[32]+=d*data[sample+32]  ST = d  WATCHOUT: not a byte displacement here!
119         fld     st0                             ; ST = d d
120         fmul    dword [esi + (31*4)]            ; ST = d*data[sample+31] d
121         fadd    dword [edi + (31*4)]            ; ST = autoc[31]+d*data[sample+31] d
122         fstp    dword [edi + (31*4)]            ; autoc[31]+=d*data[sample+31]  ST = d
123         fld     st0                             ; ST = d d
124         fmul    dword [esi + (30*4)]            ; ST = d*data[sample+30] d
125         fadd    dword [edi + (30*4)]            ; ST = autoc[30]+d*data[sample+30] d
126         fstp    dword [edi + (30*4)]            ; autoc[30]+=d*data[sample+30]  ST = d
127         fld     st0                             ; ST = d d
128         fmul    dword [esi + (29*4)]            ; ST = d*data[sample+29] d
129         fadd    dword [edi + (29*4)]            ; ST = autoc[29]+d*data[sample+29] d
130         fstp    dword [edi + (29*4)]            ; autoc[29]+=d*data[sample+29]  ST = d
131         fld     st0                             ; ST = d d
132         fmul    dword [esi + (28*4)]            ; ST = d*data[sample+28] d
133         fadd    dword [edi + (28*4)]            ; ST = autoc[28]+d*data[sample+28] d
134         fstp    dword [edi + (28*4)]            ; autoc[28]+=d*data[sample+28]  ST = d
135         fld     st0                             ; ST = d d
136         fmul    dword [esi + (27*4)]            ; ST = d*data[sample+27] d
137         fadd    dword [edi + (27*4)]            ; ST = autoc[27]+d*data[sample+27] d
138         fstp    dword [edi + (27*4)]            ; autoc[27]+=d*data[sample+27]  ST = d
139         fld     st0                             ; ST = d d
140         fmul    dword [esi + (26*4)]            ; ST = d*data[sample+26] d
141         fadd    dword [edi + (26*4)]            ; ST = autoc[26]+d*data[sample+26] d
142         fstp    dword [edi + (26*4)]            ; autoc[26]+=d*data[sample+26]  ST = d
143         fld     st0                             ; ST = d d
144         fmul    dword [esi + (25*4)]            ; ST = d*data[sample+25] d
145         fadd    dword [edi + (25*4)]            ; ST = autoc[25]+d*data[sample+25] d
146         fstp    dword [edi + (25*4)]            ; autoc[25]+=d*data[sample+25]  ST = d
147         fld     st0                             ; ST = d d
148         fmul    dword [esi + (24*4)]            ; ST = d*data[sample+24] d
149         fadd    dword [edi + (24*4)]            ; ST = autoc[24]+d*data[sample+24] d
150         fstp    dword [edi + (24*4)]            ; autoc[24]+=d*data[sample+24]  ST = d
151         fld     st0                             ; ST = d d
152         fmul    dword [esi + (23*4)]            ; ST = d*data[sample+23] d
153         fadd    dword [edi + (23*4)]            ; ST = autoc[23]+d*data[sample+23] d
154         fstp    dword [edi + (23*4)]            ; autoc[23]+=d*data[sample+23]  ST = d
155         fld     st0                             ; ST = d d
156         fmul    dword [esi + (22*4)]            ; ST = d*data[sample+22] d
157         fadd    dword [edi + (22*4)]            ; ST = autoc[22]+d*data[sample+22] d
158         fstp    dword [edi + (22*4)]            ; autoc[22]+=d*data[sample+22]  ST = d
159         fld     st0                             ; ST = d d
160         fmul    dword [esi + (21*4)]            ; ST = d*data[sample+21] d
161         fadd    dword [edi + (21*4)]            ; ST = autoc[21]+d*data[sample+21] d
162         fstp    dword [edi + (21*4)]            ; autoc[21]+=d*data[sample+21]  ST = d
163         fld     st0                             ; ST = d d
164         fmul    dword [esi + (20*4)]            ; ST = d*data[sample+20] d
165         fadd    dword [edi + (20*4)]            ; ST = autoc[20]+d*data[sample+20] d
166         fstp    dword [edi + (20*4)]            ; autoc[20]+=d*data[sample+20]  ST = d
167         fld     st0                             ; ST = d d
168         fmul    dword [esi + (19*4)]            ; ST = d*data[sample+19] d
169         fadd    dword [edi + (19*4)]            ; ST = autoc[19]+d*data[sample+19] d
170         fstp    dword [edi + (19*4)]            ; autoc[19]+=d*data[sample+19]  ST = d
171         fld     st0                             ; ST = d d
172         fmul    dword [esi + (18*4)]            ; ST = d*data[sample+18] d
173         fadd    dword [edi + (18*4)]            ; ST = autoc[18]+d*data[sample+18] d
174         fstp    dword [edi + (18*4)]            ; autoc[18]+=d*data[sample+18]  ST = d
175         fld     st0                             ; ST = d d
176         fmul    dword [esi + (17*4)]            ; ST = d*data[sample+17] d
177         fadd    dword [edi + (17*4)]            ; ST = autoc[17]+d*data[sample+17] d
178         fstp    dword [edi + (17*4)]            ; autoc[17]+=d*data[sample+17]  ST = d
179         fld     st0                             ; ST = d d
180         fmul    dword [esi + (16*4)]            ; ST = d*data[sample+16] d
181         fadd    dword [edi + (16*4)]            ; ST = autoc[16]+d*data[sample+16] d
182         fstp    dword [edi + (16*4)]            ; autoc[16]+=d*data[sample+16]  ST = d
183         fld     st0                             ; ST = d d
184         fmul    dword [esi + (15*4)]            ; ST = d*data[sample+15] d
185         fadd    dword [edi + (15*4)]            ; ST = autoc[15]+d*data[sample+15] d
186         fstp    dword [edi + (15*4)]            ; autoc[15]+=d*data[sample+15]  ST = d
187         fld     st0                             ; ST = d d
188         fmul    dword [esi + (14*4)]            ; ST = d*data[sample+14] d
189         fadd    dword [edi + (14*4)]            ; ST = autoc[14]+d*data[sample+14] d
190         fstp    dword [edi + (14*4)]            ; autoc[14]+=d*data[sample+14]  ST = d
191         fld     st0                             ; ST = d d
192         fmul    dword [esi + (13*4)]            ; ST = d*data[sample+13] d
193         fadd    dword [edi + (13*4)]            ; ST = autoc[13]+d*data[sample+13] d
194         fstp    dword [edi + (13*4)]            ; autoc[13]+=d*data[sample+13]  ST = d
195         fld     st0                             ; ST = d d
196         fmul    dword [esi + (12*4)]            ; ST = d*data[sample+12] d
197         fadd    dword [edi + (12*4)]            ; ST = autoc[12]+d*data[sample+12] d
198         fstp    dword [edi + (12*4)]            ; autoc[12]+=d*data[sample+12]  ST = d
199         fld     st0                             ; ST = d d
200         fmul    dword [esi + (11*4)]            ; ST = d*data[sample+11] d
201         fadd    dword [edi + (11*4)]            ; ST = autoc[11]+d*data[sample+11] d
202         fstp    dword [edi + (11*4)]            ; autoc[11]+=d*data[sample+11]  ST = d
203         fld     st0                             ; ST = d d
204         fmul    dword [esi + (10*4)]            ; ST = d*data[sample+10] d
205         fadd    dword [edi + (10*4)]            ; ST = autoc[10]+d*data[sample+10] d
206         fstp    dword [edi + (10*4)]            ; autoc[10]+=d*data[sample+10]  ST = d
207         fld     st0                             ; ST = d d
208         fmul    dword [esi + ( 9*4)]            ; ST = d*data[sample+9] d
209         fadd    dword [edi + ( 9*4)]            ; ST = autoc[9]+d*data[sample+9] d
210         fstp    dword [edi + ( 9*4)]            ; autoc[9]+=d*data[sample+9]  ST = d
211         fld     st0                             ; ST = d d
212         fmul    dword [esi + ( 8*4)]            ; ST = d*data[sample+8] d
213         fadd    dword [edi + ( 8*4)]            ; ST = autoc[8]+d*data[sample+8] d
214         fstp    dword [edi + ( 8*4)]            ; autoc[8]+=d*data[sample+8]  ST = d
215         fld     st0                             ; ST = d d
216         fmul    dword [esi + ( 7*4)]            ; ST = d*data[sample+7] d
217         fadd    dword [edi + ( 7*4)]            ; ST = autoc[7]+d*data[sample+7] d
218         fstp    dword [edi + ( 7*4)]            ; autoc[7]+=d*data[sample+7]  ST = d
219         fld     st0                             ; ST = d d
220         fmul    dword [esi + ( 6*4)]            ; ST = d*data[sample+6] d
221         fadd    dword [edi + ( 6*4)]            ; ST = autoc[6]+d*data[sample+6] d
222         fstp    dword [edi + ( 6*4)]            ; autoc[6]+=d*data[sample+6]  ST = d
223         fld     st0                             ; ST = d d
224         fmul    dword [esi + ( 5*4)]            ; ST = d*data[sample+4] d
225         fadd    dword [edi + ( 5*4)]            ; ST = autoc[4]+d*data[sample+4] d
226         fstp    dword [edi + ( 5*4)]            ; autoc[4]+=d*data[sample+4]  ST = d
227         fld     st0                             ; ST = d d
228         fmul    dword [esi + ( 4*4)]            ; ST = d*data[sample+4] d
229         fadd    dword [edi + ( 4*4)]            ; ST = autoc[4]+d*data[sample+4] d
230         fstp    dword [edi + ( 4*4)]            ; autoc[4]+=d*data[sample+4]  ST = d
231         fld     st0                             ; ST = d d
232         fmul    dword [esi + ( 3*4)]            ; ST = d*data[sample+3] d
233         fadd    dword [edi + ( 3*4)]            ; ST = autoc[3]+d*data[sample+3] d
234         fstp    dword [edi + ( 3*4)]            ; autoc[3]+=d*data[sample+3]  ST = d
235         fld     st0                             ; ST = d d
236         fmul    dword [esi + ( 2*4)]            ; ST = d*data[sample+2] d
237         fadd    dword [edi + ( 2*4)]            ; ST = autoc[2]+d*data[sample+2] d
238         fstp    dword [edi + ( 2*4)]            ; autoc[2]+=d*data[sample+2]  ST = d
239         fld     st0                             ; ST = d d
240         fmul    dword [esi + ( 1*4)]            ; ST = d*data[sample+1] d
241         fadd    dword [edi + ( 1*4)]            ; ST = autoc[1]+d*data[sample+1] d
242         fstp    dword [edi + ( 1*4)]            ; autoc[1]+=d*data[sample+1]  ST = d
243         fld     st0                             ; ST = d d
244         fmul    dword [esi]                     ; ST = d*data[sample] d                 WATCHOUT: no displacement byte here!
245         fadd    dword [edi]                     ; ST = autoc[0]+d*data[sample] d        WATCHOUT: no displacement byte here!
246         fstp    dword [edi]                     ; autoc[0]+=d*data[sample]  ST = d      WATCHOUT: no displacement byte here!
247 .jumper1_0:
248
249         fstp    st0                             ; pop d, ST = empty
250         add     esi, byte 4                     ; sample++
251         dec     ecx
252         jz      .loop1_end
253         fld     dword [esi]                     ; ST = d <- data[sample]
254         jmp     edx
255 .loop1_end:
256
257         ;       for(; sample < data_len; sample++) {
258         ;               d = data[sample];
259         ;               for(coeff = 0; coeff < data_len - sample; coeff++)
260         ;                       autoc[coeff] += d * data[sample+coeff];
261         ;       }
262         mov     ecx, [esp + 24]                 ; ecx <- lag
263         dec     ecx                             ; ecx <- lag - 1
264         jz      near .end                       ; skip loop if 0 (i.e. lag == 1)
265
266         fld     dword [esi]                     ; ST = d <- data[sample]
267         mov     eax, ecx                        ; eax <- lag - 1 == data_len - sample the first time through
268         ; each iteration is 11 bytes so we need (-eax)*11, so we do (-12*eax + eax)
269         lea     edx, [eax + eax*2]
270         neg     edx
271         lea     edx, [eax + edx*4 + .jumper2_0 - .get_eip2]
272         call    .get_eip2
273 .get_eip2:
274         pop     ebx
275         add     edx, ebx
276         inc     edx                             ; compensate for the shorter opcode on the last iteration
277         inc     edx                             ; compensate for the shorter opcode on the last iteration
278         inc     edx                             ; compensate for the shorter opcode on the last iteration
279         jmp     edx
280
281         fld     st0                             ; ST = d d
282         fmul    dword [esi + (31*4)]            ; ST = d*data[sample+31] d
283         fadd    dword [edi + (31*4)]            ; ST = autoc[31]+d*data[sample+31] d
284         fstp    dword [edi + (31*4)]            ; autoc[31]+=d*data[sample+31]  ST = d
285         fld     st0                             ; ST = d d
286         fmul    dword [esi + (30*4)]            ; ST = d*data[sample+30] d
287         fadd    dword [edi + (30*4)]            ; ST = autoc[30]+d*data[sample+30] d
288         fstp    dword [edi + (30*4)]            ; autoc[30]+=d*data[sample+30]  ST = d
289         fld     st0                             ; ST = d d
290         fmul    dword [esi + (29*4)]            ; ST = d*data[sample+29] d
291         fadd    dword [edi + (29*4)]            ; ST = autoc[29]+d*data[sample+29] d
292         fstp    dword [edi + (29*4)]            ; autoc[29]+=d*data[sample+29]  ST = d
293         fld     st0                             ; ST = d d
294         fmul    dword [esi + (28*4)]            ; ST = d*data[sample+28] d
295         fadd    dword [edi + (28*4)]            ; ST = autoc[28]+d*data[sample+28] d
296         fstp    dword [edi + (28*4)]            ; autoc[28]+=d*data[sample+28]  ST = d
297         fld     st0                             ; ST = d d
298         fmul    dword [esi + (27*4)]            ; ST = d*data[sample+27] d
299         fadd    dword [edi + (27*4)]            ; ST = autoc[27]+d*data[sample+27] d
300         fstp    dword [edi + (27*4)]            ; autoc[27]+=d*data[sample+27]  ST = d
301         fld     st0                             ; ST = d d
302         fmul    dword [esi + (26*4)]            ; ST = d*data[sample+26] d
303         fadd    dword [edi + (26*4)]            ; ST = autoc[26]+d*data[sample+26] d
304         fstp    dword [edi + (26*4)]            ; autoc[26]+=d*data[sample+26]  ST = d
305         fld     st0                             ; ST = d d
306         fmul    dword [esi + (25*4)]            ; ST = d*data[sample+25] d
307         fadd    dword [edi + (25*4)]            ; ST = autoc[25]+d*data[sample+25] d
308         fstp    dword [edi + (25*4)]            ; autoc[25]+=d*data[sample+25]  ST = d
309         fld     st0                             ; ST = d d
310         fmul    dword [esi + (24*4)]            ; ST = d*data[sample+24] d
311         fadd    dword [edi + (24*4)]            ; ST = autoc[24]+d*data[sample+24] d
312         fstp    dword [edi + (24*4)]            ; autoc[24]+=d*data[sample+24]  ST = d
313         fld     st0                             ; ST = d d
314         fmul    dword [esi + (23*4)]            ; ST = d*data[sample+23] d
315         fadd    dword [edi + (23*4)]            ; ST = autoc[23]+d*data[sample+23] d
316         fstp    dword [edi + (23*4)]            ; autoc[23]+=d*data[sample+23]  ST = d
317         fld     st0                             ; ST = d d
318         fmul    dword [esi + (22*4)]            ; ST = d*data[sample+22] d
319         fadd    dword [edi + (22*4)]            ; ST = autoc[22]+d*data[sample+22] d
320         fstp    dword [edi + (22*4)]            ; autoc[22]+=d*data[sample+22]  ST = d
321         fld     st0                             ; ST = d d
322         fmul    dword [esi + (21*4)]            ; ST = d*data[sample+21] d
323         fadd    dword [edi + (21*4)]            ; ST = autoc[21]+d*data[sample+21] d
324         fstp    dword [edi + (21*4)]            ; autoc[21]+=d*data[sample+21]  ST = d
325         fld     st0                             ; ST = d d
326         fmul    dword [esi + (20*4)]            ; ST = d*data[sample+20] d
327         fadd    dword [edi + (20*4)]            ; ST = autoc[20]+d*data[sample+20] d
328         fstp    dword [edi + (20*4)]            ; autoc[20]+=d*data[sample+20]  ST = d
329         fld     st0                             ; ST = d d
330         fmul    dword [esi + (19*4)]            ; ST = d*data[sample+19] d
331         fadd    dword [edi + (19*4)]            ; ST = autoc[19]+d*data[sample+19] d
332         fstp    dword [edi + (19*4)]            ; autoc[19]+=d*data[sample+19]  ST = d
333         fld     st0                             ; ST = d d
334         fmul    dword [esi + (18*4)]            ; ST = d*data[sample+18] d
335         fadd    dword [edi + (18*4)]            ; ST = autoc[18]+d*data[sample+18] d
336         fstp    dword [edi + (18*4)]            ; autoc[18]+=d*data[sample+18]  ST = d
337         fld     st0                             ; ST = d d
338         fmul    dword [esi + (17*4)]            ; ST = d*data[sample+17] d
339         fadd    dword [edi + (17*4)]            ; ST = autoc[17]+d*data[sample+17] d
340         fstp    dword [edi + (17*4)]            ; autoc[17]+=d*data[sample+17]  ST = d
341         fld     st0                             ; ST = d d
342         fmul    dword [esi + (16*4)]            ; ST = d*data[sample+16] d
343         fadd    dword [edi + (16*4)]            ; ST = autoc[16]+d*data[sample+16] d
344         fstp    dword [edi + (16*4)]            ; autoc[16]+=d*data[sample+16]  ST = d
345         fld     st0                             ; ST = d d
346         fmul    dword [esi + (15*4)]            ; ST = d*data[sample+15] d
347         fadd    dword [edi + (15*4)]            ; ST = autoc[15]+d*data[sample+15] d
348         fstp    dword [edi + (15*4)]            ; autoc[15]+=d*data[sample+15]  ST = d
349         fld     st0                             ; ST = d d
350         fmul    dword [esi + (14*4)]            ; ST = d*data[sample+14] d
351         fadd    dword [edi + (14*4)]            ; ST = autoc[14]+d*data[sample+14] d
352         fstp    dword [edi + (14*4)]            ; autoc[14]+=d*data[sample+14]  ST = d
353         fld     st0                             ; ST = d d
354         fmul    dword [esi + (13*4)]            ; ST = d*data[sample+13] d
355         fadd    dword [edi + (13*4)]            ; ST = autoc[13]+d*data[sample+13] d
356         fstp    dword [edi + (13*4)]            ; autoc[13]+=d*data[sample+13]  ST = d
357         fld     st0                             ; ST = d d
358         fmul    dword [esi + (12*4)]            ; ST = d*data[sample+12] d
359         fadd    dword [edi + (12*4)]            ; ST = autoc[12]+d*data[sample+12] d
360         fstp    dword [edi + (12*4)]            ; autoc[12]+=d*data[sample+12]  ST = d
361         fld     st0                             ; ST = d d
362         fmul    dword [esi + (11*4)]            ; ST = d*data[sample+11] d
363         fadd    dword [edi + (11*4)]            ; ST = autoc[11]+d*data[sample+11] d
364         fstp    dword [edi + (11*4)]            ; autoc[11]+=d*data[sample+11]  ST = d
365         fld     st0                             ; ST = d d
366         fmul    dword [esi + (10*4)]            ; ST = d*data[sample+10] d
367         fadd    dword [edi + (10*4)]            ; ST = autoc[10]+d*data[sample+10] d
368         fstp    dword [edi + (10*4)]            ; autoc[10]+=d*data[sample+10]  ST = d
369         fld     st0                             ; ST = d d
370         fmul    dword [esi + ( 9*4)]            ; ST = d*data[sample+9] d
371         fadd    dword [edi + ( 9*4)]            ; ST = autoc[9]+d*data[sample+9] d
372         fstp    dword [edi + ( 9*4)]            ; autoc[9]+=d*data[sample+9]  ST = d
373         fld     st0                             ; ST = d d
374         fmul    dword [esi + ( 8*4)]            ; ST = d*data[sample+8] d
375         fadd    dword [edi + ( 8*4)]            ; ST = autoc[8]+d*data[sample+8] d
376         fstp    dword [edi + ( 8*4)]            ; autoc[8]+=d*data[sample+8]  ST = d
377         fld     st0                             ; ST = d d
378         fmul    dword [esi + ( 7*4)]            ; ST = d*data[sample+7] d
379         fadd    dword [edi + ( 7*4)]            ; ST = autoc[7]+d*data[sample+7] d
380         fstp    dword [edi + ( 7*4)]            ; autoc[7]+=d*data[sample+7]  ST = d
381         fld     st0                             ; ST = d d
382         fmul    dword [esi + ( 6*4)]            ; ST = d*data[sample+6] d
383         fadd    dword [edi + ( 6*4)]            ; ST = autoc[6]+d*data[sample+6] d
384         fstp    dword [edi + ( 6*4)]            ; autoc[6]+=d*data[sample+6]  ST = d
385         fld     st0                             ; ST = d d
386         fmul    dword [esi + ( 5*4)]            ; ST = d*data[sample+4] d
387         fadd    dword [edi + ( 5*4)]            ; ST = autoc[4]+d*data[sample+4] d
388         fstp    dword [edi + ( 5*4)]            ; autoc[4]+=d*data[sample+4]  ST = d
389         fld     st0                             ; ST = d d
390         fmul    dword [esi + ( 4*4)]            ; ST = d*data[sample+4] d
391         fadd    dword [edi + ( 4*4)]            ; ST = autoc[4]+d*data[sample+4] d
392         fstp    dword [edi + ( 4*4)]            ; autoc[4]+=d*data[sample+4]  ST = d
393         fld     st0                             ; ST = d d
394         fmul    dword [esi + ( 3*4)]            ; ST = d*data[sample+3] d
395         fadd    dword [edi + ( 3*4)]            ; ST = autoc[3]+d*data[sample+3] d
396         fstp    dword [edi + ( 3*4)]            ; autoc[3]+=d*data[sample+3]  ST = d
397         fld     st0                             ; ST = d d
398         fmul    dword [esi + ( 2*4)]            ; ST = d*data[sample+2] d
399         fadd    dword [edi + ( 2*4)]            ; ST = autoc[2]+d*data[sample+2] d
400         fstp    dword [edi + ( 2*4)]            ; autoc[2]+=d*data[sample+2]  ST = d
401         fld     st0                             ; ST = d d
402         fmul    dword [esi + ( 1*4)]            ; ST = d*data[sample+1] d
403         fadd    dword [edi + ( 1*4)]            ; ST = autoc[1]+d*data[sample+1] d
404         fstp    dword [edi + ( 1*4)]            ; autoc[1]+=d*data[sample+1]  ST = d
405         fld     st0                             ; ST = d d
406         fmul    dword [esi]                     ; ST = d*data[sample] d                 WATCHOUT: no displacement byte here!
407         fadd    dword [edi]                     ; ST = autoc[0]+d*data[sample] d        WATCHOUT: no displacement byte here!
408         fstp    dword [edi]                     ; autoc[0]+=d*data[sample]  ST = d      WATCHOUT: no displacement byte here!
409 .jumper2_0:
410
411         fstp    st0                             ; pop d, ST = empty
412         add     esi, byte 4                     ; sample++
413         dec     ecx
414         jz      .loop2_end
415         add     edx, byte 11                    ; adjust our inner loop counter by adjusting the jump target
416         fld     dword [esi]                     ; ST = d <- data[sample]
417         jmp     edx
418 .loop2_end:
419
420 .end:
421         pop     ebx
422         pop     edi
423         pop     esi
424         ret
425
426         ALIGN 16
427 cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4
428         ;[esp + 16] == autoc[]
429         ;[esp + 12] == lag
430         ;[esp + 8] == data_len
431         ;[esp + 4] == data[]
432
433         ;ASSERT(lag > 0)
434         ;ASSERT(lag <= 4)
435         ;ASSERT(lag <= data_len)
436
437         ;       for(coeff = 0; coeff < lag; coeff++)
438         ;               autoc[coeff] = 0.0;
439         xorps   xmm5, xmm5
440
441         mov     edx, [esp + 8]                  ; edx == data_len
442         mov     eax, [esp + 4]                  ; eax == &data[sample] <- &data[0]
443
444         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[0]
445         add     eax, 4
446         movaps  xmm2, xmm0                      ; xmm2 = 0,0,0,data[0]
447         shufps  xmm0, xmm0, 0                   ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0]
448 .warmup:                                        ; xmm2 == data[sample-3],data[sample-2],data[sample-1],data[sample]
449         mulps   xmm0, xmm2                      ; xmm0 = xmm0 * xmm2
450         addps   xmm5, xmm0                      ; xmm5 += xmm0 * xmm2
451         dec     edx
452         jz      .loop_end
453         ALIGN 16
454 .loop_start:
455         ; start by reading the next sample
456         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[sample]
457         add     eax, 4
458         shufps  xmm0, xmm0, 0                   ; xmm0 = data[sample],data[sample],data[sample],data[sample]
459         shufps  xmm2, xmm2, 93h                 ; 93h=2-1-0-3 => xmm2 gets rotated left by one float
460         movss   xmm2, xmm0
461         mulps   xmm0, xmm2                      ; xmm0 = xmm0 * xmm2
462         addps   xmm5, xmm0                      ; xmm5 += xmm0 * xmm2
463         dec     edx
464         jnz     .loop_start
465 .loop_end:
466         ; store autoc
467         mov     edx, [esp + 16]                 ; edx == autoc
468         movups  [edx], xmm5
469
470 .end:
471         ret
472
473         ALIGN 16
474 cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8
475         ;[esp + 16] == autoc[]
476         ;[esp + 12] == lag
477         ;[esp + 8] == data_len
478         ;[esp + 4] == data[]
479
480         ;ASSERT(lag > 0)
481         ;ASSERT(lag <= 8)
482         ;ASSERT(lag <= data_len)
483
484         ;       for(coeff = 0; coeff < lag; coeff++)
485         ;               autoc[coeff] = 0.0;
486         xorps   xmm5, xmm5
487         xorps   xmm6, xmm6
488
489         mov     edx, [esp + 8]                  ; edx == data_len
490         mov     eax, [esp + 4]                  ; eax == &data[sample] <- &data[0]
491
492         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[0]
493         add     eax, 4
494         movaps  xmm2, xmm0                      ; xmm2 = 0,0,0,data[0]
495         shufps  xmm0, xmm0, 0                   ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0]
496         movaps  xmm1, xmm0                      ; xmm1 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0]
497         xorps   xmm3, xmm3                      ; xmm3 = 0,0,0,0
498 .warmup:                                        ; xmm3:xmm2 == data[sample-7],data[sample-6],...,data[sample]
499         mulps   xmm0, xmm2
500         mulps   xmm1, xmm3                      ; xmm1:xmm0 = xmm1:xmm0 * xmm3:xmm2
501         addps   xmm5, xmm0
502         addps   xmm6, xmm1                      ; xmm6:xmm5 += xmm1:xmm0 * xmm3:xmm2
503         dec     edx
504         jz      .loop_end
505         ALIGN 16
506 .loop_start:
507         ; start by reading the next sample
508         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[sample]
509         ; here we reorder the instructions; see the (#) indexes for a logical order
510         shufps  xmm2, xmm2, 93h                 ; (3) 93h=2-1-0-3 => xmm2 gets rotated left by one float
511         add     eax, 4                          ; (0)
512         shufps  xmm3, xmm3, 93h                 ; (4) 93h=2-1-0-3 => xmm3 gets rotated left by one float
513         shufps  xmm0, xmm0, 0                   ; (1) xmm0 = data[sample],data[sample],data[sample],data[sample]
514         movss   xmm3, xmm2                      ; (5)
515         movaps  xmm1, xmm0                      ; (2) xmm1 = data[sample],data[sample],data[sample],data[sample]
516         movss   xmm2, xmm0                      ; (6)
517         mulps   xmm1, xmm3                      ; (8)
518         mulps   xmm0, xmm2                      ; (7) xmm1:xmm0 = xmm1:xmm0 * xmm3:xmm2
519         addps   xmm6, xmm1                      ; (10)
520         addps   xmm5, xmm0                      ; (9) xmm6:xmm5 += xmm1:xmm0 * xmm3:xmm2
521         dec     edx
522         jnz     .loop_start
523 .loop_end:
524         ; store autoc
525         mov     edx, [esp + 16]                 ; edx == autoc
526         movups  [edx], xmm5
527         movups  [edx + 16], xmm6
528
529 .end:
530         ret
531
532         ALIGN 16
533 cident FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12
534         ;[esp + 16] == autoc[]
535         ;[esp + 12] == lag
536         ;[esp + 8] == data_len
537         ;[esp + 4] == data[]
538
539         ;ASSERT(lag > 0)
540         ;ASSERT(lag <= 12)
541         ;ASSERT(lag <= data_len)
542
543         ;       for(coeff = 0; coeff < lag; coeff++)
544         ;               autoc[coeff] = 0.0;
545         xorps   xmm5, xmm5
546         xorps   xmm6, xmm6
547         xorps   xmm7, xmm7
548
549         mov     edx, [esp + 8]                  ; edx == data_len
550         mov     eax, [esp + 4]                  ; eax == &data[sample] <- &data[0]
551
552         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[0]
553         add     eax, 4
554         movaps  xmm2, xmm0                      ; xmm2 = 0,0,0,data[0]
555         shufps  xmm0, xmm0, 0                   ; xmm0 == data[sample],data[sample],data[sample],data[sample] = data[0],data[0],data[0],data[0]
556         xorps   xmm3, xmm3                      ; xmm3 = 0,0,0,0
557         xorps   xmm4, xmm4                      ; xmm4 = 0,0,0,0
558 .warmup:                                        ; xmm3:xmm2 == data[sample-7],data[sample-6],...,data[sample]
559         movaps  xmm1, xmm0
560         mulps   xmm1, xmm2
561         addps   xmm5, xmm1
562         movaps  xmm1, xmm0
563         mulps   xmm1, xmm3
564         addps   xmm6, xmm1
565         mulps   xmm0, xmm4
566         addps   xmm7, xmm0                      ; xmm7:xmm6:xmm5 += xmm0:xmm0:xmm0 * xmm4:xmm3:xmm2
567         dec     edx
568         jz      .loop_end
569         ALIGN 16
570 .loop_start:
571         ; start by reading the next sample
572         movss   xmm0, [eax]                     ; xmm0 = 0,0,0,data[sample]
573         add     eax, 4
574         shufps  xmm0, xmm0, 0                   ; xmm0 = data[sample],data[sample],data[sample],data[sample]
575
576         ; shift xmm4:xmm3:xmm2 left by one float
577         shufps  xmm2, xmm2, 93h                 ; 93h=2-1-0-3 => xmm2 gets rotated left by one float
578         shufps  xmm3, xmm3, 93h                 ; 93h=2-1-0-3 => xmm3 gets rotated left by one float
579         shufps  xmm4, xmm4, 93h                 ; 93h=2-1-0-3 => xmm4 gets rotated left by one float
580         movss   xmm4, xmm3
581         movss   xmm3, xmm2
582         movss   xmm2, xmm0
583
584         ; xmm7:xmm6:xmm5 += xmm0:xmm0:xmm0 * xmm3:xmm3:xmm2
585         movaps  xmm1, xmm0
586         mulps   xmm1, xmm2
587         addps   xmm5, xmm1
588         movaps  xmm1, xmm0
589         mulps   xmm1, xmm3
590         addps   xmm6, xmm1
591         mulps   xmm0, xmm4
592         addps   xmm7, xmm0
593
594         dec     edx
595         jnz     .loop_start
596 .loop_end:
597         ; store autoc
598         mov     edx, [esp + 16]                 ; edx == autoc
599         movups  [edx], xmm5
600         movups  [edx + 16], xmm6
601         movups  [edx + 32], xmm7
602
603 .end:
604         ret
605
606         align 16
607 cident FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow
608         ;[ebp + 32] autoc
609         ;[ebp + 28] lag
610         ;[ebp + 24] data_len
611         ;[ebp + 20] data
612
613         push    ebp
614         push    ebx
615         push    esi
616         push    edi
617         mov     ebp, esp
618
619         mov     esi, [ebp + 20]
620         mov     edi, [ebp + 24]
621         mov     edx, [ebp + 28]
622         mov     eax, edx
623         neg     eax
624         and     esp, byte -8
625         lea     esp, [esp + 4 * eax]
626         mov     ecx, edx
627         xor     eax, eax
628 .loop0:
629         dec     ecx
630         mov     [esp + 4 * ecx], eax
631         jnz     short .loop0
632
633         mov     eax, edi
634         sub     eax, edx
635         mov     ebx, edx
636         and     ebx, byte 1
637         sub     eax, ebx
638         lea     ecx, [esi + 4 * eax - 12]
639         cmp     esi, ecx
640         mov     eax, esi
641         ja      short .loop2_pre
642         align   16              ;8 nops
643 .loop1_i:
644         movd    mm0, [eax]
645         movd    mm2, [eax + 4]
646         movd    mm4, [eax + 8]
647         movd    mm6, [eax + 12]
648         mov     ebx, edx
649         punpckldq       mm0, mm0
650         punpckldq       mm2, mm2
651         punpckldq       mm4, mm4
652         punpckldq       mm6, mm6
653         align   16              ;3 nops
654 .loop1_j:
655         sub     ebx, byte 2
656         movd    mm1, [eax + 4 * ebx]
657         movd    mm3, [eax + 4 * ebx + 4]
658         movd    mm5, [eax + 4 * ebx + 8]
659         movd    mm7, [eax + 4 * ebx + 12]
660         punpckldq       mm1, mm3
661         punpckldq       mm3, mm5
662         pfmul   mm1, mm0
663         punpckldq       mm5, mm7
664         pfmul   mm3, mm2
665         punpckldq       mm7, [eax + 4 * ebx + 16]
666         pfmul   mm5, mm4
667         pfmul   mm7, mm6
668         pfadd   mm1, mm3
669         movq    mm3, [esp + 4 * ebx]
670         pfadd   mm5, mm7
671         pfadd   mm1, mm5
672         pfadd   mm3, mm1
673         movq    [esp + 4 * ebx], mm3
674         jg      short .loop1_j
675
676         add     eax, byte 16
677         cmp     eax, ecx
678         jb      short .loop1_i
679
680 .loop2_pre:
681         mov     ebx, eax
682         sub     eax, esi
683         shr     eax, 2
684         lea     ecx, [esi + 4 * edi]
685         mov     esi, ebx
686 .loop2_i:
687         movd    mm0, [esi]
688         mov     ebx, edi
689         sub     ebx, eax
690         cmp     ebx, edx
691         jbe     short .loop2_j
692         mov     ebx, edx
693 .loop2_j:
694         dec     ebx
695         movd    mm1, [esi + 4 * ebx]
696         pfmul   mm1, mm0
697         movd    mm2, [esp + 4 * ebx]
698         pfadd   mm1, mm2
699         movd    [esp + 4 * ebx], mm1
700
701         jnz     short .loop2_j
702
703         add     esi, byte 4
704         inc     eax
705         cmp     esi, ecx
706         jnz     short .loop2_i
707
708         mov     edi, [ebp + 32]
709 .loop3:
710         dec     edx
711         mov     eax, [esp + 4 * edx]
712         mov     [edi + 4 * edx], eax
713         jnz     short .loop3
714
715         femms
716
717         mov     esp, ebp
718         pop     edi
719         pop     esi
720         pop     ebx
721         pop     ebp
722         ret
723
724 ;void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[])
725 ;
726 ;       for(i = 0; i < data_len; i++) {
727 ;               sum = 0;
728 ;               for(j = 0; j < order; j++)
729 ;                       sum += qlp_coeff[j] * data[i-j-1];
730 ;               residual[i] = data[i] - (sum >> lp_quantization);
731 ;       }
732 ;
733         ALIGN   16
734 cident FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32
735         ;[esp + 40]     residual[]
736         ;[esp + 36]     lp_quantization
737         ;[esp + 32]     order
738         ;[esp + 28]     qlp_coeff[]
739         ;[esp + 24]     data_len
740         ;[esp + 20]     data[]
741
742         ;ASSERT(order > 0)
743
744         push    ebp
745         push    ebx
746         push    esi
747         push    edi
748
749         mov     esi, [esp + 20]                 ; esi = data[]
750         mov     edi, [esp + 40]                 ; edi = residual[]
751         mov     eax, [esp + 32]                 ; eax = order
752         mov     ebx, [esp + 24]                 ; ebx = data_len
753
754         test    ebx, ebx
755         jz      near .end                       ; do nothing if data_len == 0
756 .begin:
757         cmp     eax, byte 1
758         jg      short .i_1more
759
760         mov     ecx, [esp + 28]
761         mov     edx, [ecx]                      ; edx = qlp_coeff[0]
762         mov     eax, [esi - 4]                  ; eax = data[-1]
763         mov     cl, [esp + 36]                  ; cl = lp_quantization
764         ALIGN   16
765 .i_1_loop_i:
766         imul    eax, edx
767         sar     eax, cl
768         neg     eax
769         add     eax, [esi]
770         mov     [edi], eax
771         mov     eax, [esi]
772         add     edi, byte 4
773         add     esi, byte 4
774         dec     ebx
775         jnz     .i_1_loop_i
776
777         jmp     .end
778
779 .i_1more:
780         cmp     eax, byte 32                    ; for order <= 32 there is a faster routine
781         jbe     short .i_32
782
783         ; This version is here just for completeness, since FLAC__MAX_LPC_ORDER == 32
784         ALIGN 16
785 .i_32more_loop_i:
786         xor     ebp, ebp
787         mov     ecx, [esp + 32]
788         mov     edx, ecx
789         shl     edx, 2
790         add     edx, [esp + 28]
791         neg     ecx
792         ALIGN   16
793 .i_32more_loop_j:
794         sub     edx, byte 4
795         mov     eax, [edx]
796         imul    eax, [esi + 4 * ecx]
797         add     ebp, eax
798         inc     ecx
799         jnz     short .i_32more_loop_j
800
801         mov     cl, [esp + 36]
802         sar     ebp, cl
803         neg     ebp
804         add     ebp, [esi]
805         mov     [edi], ebp
806         add     esi, byte 4
807         add     edi, byte 4
808
809         dec     ebx
810         jnz     .i_32more_loop_i
811
812         jmp     .end
813
814 .i_32:
815         sub     edi, esi
816         neg     eax
817         lea     edx, [eax + eax * 8 + .jumper_0 - .get_eip0]
818         call    .get_eip0
819 .get_eip0:
820         pop     eax
821         add     edx, eax
822         inc     edx
823         mov     eax, [esp + 28]                 ; eax = qlp_coeff[]
824         xor     ebp, ebp
825         jmp     edx
826
827         mov     ecx, [eax + 124]
828         imul    ecx, [esi - 128]
829         add     ebp, ecx
830         mov     ecx, [eax + 120]
831         imul    ecx, [esi - 124]
832         add     ebp, ecx
833         mov     ecx, [eax + 116]
834         imul    ecx, [esi - 120]
835         add     ebp, ecx
836         mov     ecx, [eax + 112]
837         imul    ecx, [esi - 116]
838         add     ebp, ecx
839         mov     ecx, [eax + 108]
840         imul    ecx, [esi - 112]
841         add     ebp, ecx
842         mov     ecx, [eax + 104]
843         imul    ecx, [esi - 108]
844         add     ebp, ecx
845         mov     ecx, [eax + 100]
846         imul    ecx, [esi - 104]
847         add     ebp, ecx
848         mov     ecx, [eax + 96]
849         imul    ecx, [esi - 100]
850         add     ebp, ecx
851         mov     ecx, [eax + 92]
852         imul    ecx, [esi - 96]
853         add     ebp, ecx
854         mov     ecx, [eax + 88]
855         imul    ecx, [esi - 92]
856         add     ebp, ecx
857         mov     ecx, [eax + 84]
858         imul    ecx, [esi - 88]
859         add     ebp, ecx
860         mov     ecx, [eax + 80]
861         imul    ecx, [esi - 84]
862         add     ebp, ecx
863         mov     ecx, [eax + 76]
864         imul    ecx, [esi - 80]
865         add     ebp, ecx
866         mov     ecx, [eax + 72]
867         imul    ecx, [esi - 76]
868         add     ebp, ecx
869         mov     ecx, [eax + 68]
870         imul    ecx, [esi - 72]
871         add     ebp, ecx
872         mov     ecx, [eax + 64]
873         imul    ecx, [esi - 68]
874         add     ebp, ecx
875         mov     ecx, [eax + 60]
876         imul    ecx, [esi - 64]
877         add     ebp, ecx
878         mov     ecx, [eax + 56]
879         imul    ecx, [esi - 60]
880         add     ebp, ecx
881         mov     ecx, [eax + 52]
882         imul    ecx, [esi - 56]
883         add     ebp, ecx
884         mov     ecx, [eax + 48]
885         imul    ecx, [esi - 52]
886         add     ebp, ecx
887         mov     ecx, [eax + 44]
888         imul    ecx, [esi - 48]
889         add     ebp, ecx
890         mov     ecx, [eax + 40]
891         imul    ecx, [esi - 44]
892         add     ebp, ecx
893         mov     ecx, [eax + 36]
894         imul    ecx, [esi - 40]
895         add     ebp, ecx
896         mov     ecx, [eax + 32]
897         imul    ecx, [esi - 36]
898         add     ebp, ecx
899         mov     ecx, [eax + 28]
900         imul    ecx, [esi - 32]
901         add     ebp, ecx
902         mov     ecx, [eax + 24]
903         imul    ecx, [esi - 28]
904         add     ebp, ecx
905         mov     ecx, [eax + 20]
906         imul    ecx, [esi - 24]
907         add     ebp, ecx
908         mov     ecx, [eax + 16]
909         imul    ecx, [esi - 20]
910         add     ebp, ecx
911         mov     ecx, [eax + 12]
912         imul    ecx, [esi - 16]
913         add     ebp, ecx
914         mov     ecx, [eax + 8]
915         imul    ecx, [esi - 12]
916         add     ebp, ecx
917         mov     ecx, [eax + 4]
918         imul    ecx, [esi - 8]
919         add     ebp, ecx
920         mov     ecx, [eax]                      ; there is one byte missing
921         imul    ecx, [esi - 4]
922         add     ebp, ecx
923 .jumper_0:
924
925         mov     cl, [esp + 36]
926         sar     ebp, cl
927         neg     ebp
928         add     ebp, [esi]
929         mov     [edi + esi], ebp
930         add     esi, byte 4
931
932         dec     ebx
933         jz      short .end
934         xor     ebp, ebp
935         jmp     edx
936
937 .end:
938         pop     edi
939         pop     esi
940         pop     ebx
941         pop     ebp
942         ret
943
944 ; WATCHOUT: this routine works on 16 bit data which means bits-per-sample for
945 ; the channel must be <= 16.  Especially note that this routine cannot be used
946 ; for side-channel coded 16bps channels since the effective bps is 17.
947         ALIGN   16
948 cident FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx
949         ;[esp + 40]     residual[]
950         ;[esp + 36]     lp_quantization
951         ;[esp + 32]     order
952         ;[esp + 28]     qlp_coeff[]
953         ;[esp + 24]     data_len
954         ;[esp + 20]     data[]
955
956         ;ASSERT(order > 0)
957
958         push    ebp
959         push    ebx
960         push    esi
961         push    edi
962
963         mov     esi, [esp + 20]                 ; esi = data[]
964         mov     edi, [esp + 40]                 ; edi = residual[]
965         mov     eax, [esp + 32]                 ; eax = order
966         mov     ebx, [esp + 24]                 ; ebx = data_len
967
968         test    ebx, ebx
969         jz      near .end                       ; do nothing if data_len == 0
970         dec     ebx
971         test    ebx, ebx
972         jz      near .last_one
973
974         mov     edx, [esp + 28]                 ; edx = qlp_coeff[]
975         movd    mm6, [esp + 36]                 ; mm6 = 0:lp_quantization
976         mov     ebp, esp
977
978         and     esp, 0xfffffff8
979
980         xor     ecx, ecx
981 .copy_qlp_loop:
982         push    word [edx + 4 * ecx]
983         inc     ecx
984         cmp     ecx, eax
985         jnz     short .copy_qlp_loop
986
987         and     ecx, 0x3
988         test    ecx, ecx
989         je      short .za_end
990         sub     ecx, byte 4
991 .za_loop:
992         push    word 0
993         inc     eax
994         inc     ecx
995         jnz     short .za_loop
996 .za_end:
997
998         movq    mm5, [esp + 2 * eax - 8]
999         movd    mm4, [esi - 16]
1000         punpckldq       mm4, [esi - 12]
1001         movd    mm0, [esi - 8]
1002         punpckldq       mm0, [esi - 4]
1003         packssdw        mm4, mm0
1004
1005         cmp     eax, byte 4
1006         jnbe    short .mmx_4more
1007
1008         align   16
1009 .mmx_4_loop_i:
1010         movd    mm1, [esi]
1011         movq    mm3, mm4
1012         punpckldq       mm1, [esi + 4]
1013         psrlq   mm4, 16
1014         movq    mm0, mm1
1015         psllq   mm0, 48
1016         por     mm4, mm0
1017         movq    mm2, mm4
1018         psrlq   mm4, 16
1019         pxor    mm0, mm0
1020         punpckhdq       mm0, mm1
1021         pmaddwd mm3, mm5
1022         pmaddwd mm2, mm5
1023         psllq   mm0, 16
1024         por     mm4, mm0
1025         movq    mm0, mm3
1026         punpckldq       mm3, mm2
1027         punpckhdq       mm0, mm2
1028         paddd   mm3, mm0
1029         psrad   mm3, mm6
1030         psubd   mm1, mm3
1031         movd    [edi], mm1
1032         punpckhdq       mm1, mm1
1033         movd    [edi + 4], mm1
1034
1035         add     edi, byte 8
1036         add     esi, byte 8
1037
1038         sub     ebx, 2
1039         jg      .mmx_4_loop_i
1040         jmp     .mmx_end
1041
1042 .mmx_4more:
1043         shl     eax, 2
1044         neg     eax
1045         add     eax, byte 16
1046
1047         align   16
1048 .mmx_4more_loop_i:
1049         movd    mm1, [esi]
1050         punpckldq       mm1, [esi + 4]
1051         movq    mm3, mm4
1052         psrlq   mm4, 16
1053         movq    mm0, mm1
1054         psllq   mm0, 48
1055         por     mm4, mm0
1056         movq    mm2, mm4
1057         psrlq   mm4, 16
1058         pxor    mm0, mm0
1059         punpckhdq       mm0, mm1
1060         pmaddwd mm3, mm5
1061         pmaddwd mm2, mm5
1062         psllq   mm0, 16
1063         por     mm4, mm0
1064
1065         mov     ecx, esi
1066         add     ecx, eax
1067         mov     edx, esp
1068
1069         align   16
1070 .mmx_4more_loop_j:
1071         movd    mm0, [ecx - 16]
1072         movd    mm7, [ecx - 8]
1073         punpckldq       mm0, [ecx - 12]
1074         punpckldq       mm7, [ecx - 4]
1075         packssdw        mm0, mm7
1076         pmaddwd mm0, [edx]
1077         punpckhdq       mm7, mm7
1078         paddd   mm3, mm0
1079         movd    mm0, [ecx - 12]
1080         punpckldq       mm0, [ecx - 8]
1081         punpckldq       mm7, [ecx]
1082         packssdw        mm0, mm7
1083         pmaddwd mm0, [edx]
1084         paddd   mm2, mm0
1085
1086         add     edx, byte 8
1087         add     ecx, byte 16
1088         cmp     ecx, esi
1089         jnz     .mmx_4more_loop_j
1090
1091         movq    mm0, mm3
1092         punpckldq       mm3, mm2
1093         punpckhdq       mm0, mm2
1094         paddd   mm3, mm0
1095         psrad   mm3, mm6
1096         psubd   mm1, mm3
1097         movd    [edi], mm1
1098         punpckhdq       mm1, mm1
1099         movd    [edi + 4], mm1
1100
1101         add     edi, byte 8
1102         add     esi, byte 8
1103
1104         sub     ebx, 2
1105         jg      near .mmx_4more_loop_i
1106
1107 .mmx_end:
1108         emms
1109         mov     esp, ebp
1110 .last_one:
1111         mov     eax, [esp + 32]
1112         inc     ebx
1113         jnz     near FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32.begin
1114
1115 .end:
1116         pop     edi
1117         pop     esi
1118         pop     ebx
1119         pop     ebp
1120         ret
1121
1122 ; **********************************************************************
1123 ;
1124 ; void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[])
1125 ; {
1126 ;       unsigned i, j;
1127 ;       FLAC__int32 sum;
1128 ;
1129 ;       FLAC__ASSERT(order > 0);
1130 ;
1131 ;       for(i = 0; i < data_len; i++) {
1132 ;               sum = 0;
1133 ;               for(j = 0; j < order; j++)
1134 ;                       sum += qlp_coeff[j] * data[i-j-1];
1135 ;               data[i] = residual[i] + (sum >> lp_quantization);
1136 ;       }
1137 ; }
1138         ALIGN   16
1139 cident FLAC__lpc_restore_signal_asm_ia32
1140         ;[esp + 40]     data[]
1141         ;[esp + 36]     lp_quantization
1142         ;[esp + 32]     order
1143         ;[esp + 28]     qlp_coeff[]
1144         ;[esp + 24]     data_len
1145         ;[esp + 20]     residual[]
1146
1147         ;ASSERT(order > 0)
1148
1149         push    ebp
1150         push    ebx
1151         push    esi
1152         push    edi
1153
1154         mov     esi, [esp + 20]                 ; esi = residual[]
1155         mov     edi, [esp + 40]                 ; edi = data[]
1156         mov     eax, [esp + 32]                 ; eax = order
1157         mov     ebx, [esp + 24]                 ; ebx = data_len
1158
1159         test    ebx, ebx
1160         jz      near .end                       ; do nothing if data_len == 0
1161
1162 .begin:
1163         cmp     eax, byte 1
1164         jg      short .x87_1more
1165
1166         mov     ecx, [esp + 28]
1167         mov     edx, [ecx]
1168         mov     eax, [edi - 4]
1169         mov     cl, [esp + 36]
1170         ALIGN   16
1171 .x87_1_loop_i:
1172         imul    eax, edx
1173         sar     eax, cl
1174         add     eax, [esi]
1175         mov     [edi], eax
1176         add     esi, byte 4
1177         add     edi, byte 4
1178         dec     ebx
1179         jnz     .x87_1_loop_i
1180
1181         jmp     .end
1182
1183 .x87_1more:
1184         cmp     eax, byte 32                    ; for order <= 32 there is a faster routine
1185         jbe     short .x87_32
1186
1187         ; This version is here just for completeness, since FLAC__MAX_LPC_ORDER == 32
1188         ALIGN 16
1189 .x87_32more_loop_i:
1190         xor     ebp, ebp
1191         mov     ecx, [esp + 32]
1192         mov     edx, ecx
1193         shl     edx, 2
1194         add     edx, [esp + 28]
1195         neg     ecx
1196         ALIGN   16
1197 .x87_32more_loop_j:
1198         sub     edx, byte 4
1199         mov     eax, [edx]
1200         imul    eax, [edi + 4 * ecx]
1201         add     ebp, eax
1202         inc     ecx
1203         jnz     short .x87_32more_loop_j
1204
1205         mov     cl, [esp + 36]
1206         sar     ebp, cl
1207         add     ebp, [esi]
1208         mov     [edi], ebp
1209         add     edi, byte 4
1210         add     esi, byte 4
1211
1212         dec     ebx
1213         jnz     .x87_32more_loop_i
1214
1215         jmp     .end
1216
1217 .x87_32:
1218         sub     esi, edi
1219         neg     eax
1220         lea     edx, [eax + eax * 8 + .jumper_0 - .get_eip0]
1221         call    .get_eip0
1222 .get_eip0:
1223         pop     eax
1224         add     edx, eax
1225         inc     edx                             ; compensate for the shorter opcode on the last iteration
1226         mov     eax, [esp + 28]                 ; eax = qlp_coeff[]
1227         xor     ebp, ebp
1228         jmp     edx
1229
1230         mov     ecx, [eax + 124]                ; ecx =  qlp_coeff[31]
1231         imul    ecx, [edi - 128]                ; ecx =  qlp_coeff[31] * data[i-32]
1232         add     ebp, ecx                        ; sum += qlp_coeff[31] * data[i-32]
1233         mov     ecx, [eax + 120]                ; ecx =  qlp_coeff[30]
1234         imul    ecx, [edi - 124]                ; ecx =  qlp_coeff[30] * data[i-31]
1235         add     ebp, ecx                        ; sum += qlp_coeff[30] * data[i-31]
1236         mov     ecx, [eax + 116]                ; ecx =  qlp_coeff[29]
1237         imul    ecx, [edi - 120]                ; ecx =  qlp_coeff[29] * data[i-30]
1238         add     ebp, ecx                        ; sum += qlp_coeff[29] * data[i-30]
1239         mov     ecx, [eax + 112]                ; ecx =  qlp_coeff[28]
1240         imul    ecx, [edi - 116]                ; ecx =  qlp_coeff[28] * data[i-29]
1241         add     ebp, ecx                        ; sum += qlp_coeff[28] * data[i-29]
1242         mov     ecx, [eax + 108]                ; ecx =  qlp_coeff[27]
1243         imul    ecx, [edi - 112]                ; ecx =  qlp_coeff[27] * data[i-28]
1244         add     ebp, ecx                        ; sum += qlp_coeff[27] * data[i-28]
1245         mov     ecx, [eax + 104]                ; ecx =  qlp_coeff[26]
1246         imul    ecx, [edi - 108]                ; ecx =  qlp_coeff[26] * data[i-27]
1247         add     ebp, ecx                        ; sum += qlp_coeff[26] * data[i-27]
1248         mov     ecx, [eax + 100]                ; ecx =  qlp_coeff[25]
1249         imul    ecx, [edi - 104]                ; ecx =  qlp_coeff[25] * data[i-26]
1250         add     ebp, ecx                        ; sum += qlp_coeff[25] * data[i-26]
1251         mov     ecx, [eax + 96]                 ; ecx =  qlp_coeff[24]
1252         imul    ecx, [edi - 100]                ; ecx =  qlp_coeff[24] * data[i-25]
1253         add     ebp, ecx                        ; sum += qlp_coeff[24] * data[i-25]
1254         mov     ecx, [eax + 92]                 ; ecx =  qlp_coeff[23]
1255         imul    ecx, [edi - 96]                 ; ecx =  qlp_coeff[23] * data[i-24]
1256         add     ebp, ecx                        ; sum += qlp_coeff[23] * data[i-24]
1257         mov     ecx, [eax + 88]                 ; ecx =  qlp_coeff[22]
1258         imul    ecx, [edi - 92]                 ; ecx =  qlp_coeff[22] * data[i-23]
1259         add     ebp, ecx                        ; sum += qlp_coeff[22] * data[i-23]
1260         mov     ecx, [eax + 84]                 ; ecx =  qlp_coeff[21]
1261         imul    ecx, [edi - 88]                 ; ecx =  qlp_coeff[21] * data[i-22]
1262         add     ebp, ecx                        ; sum += qlp_coeff[21] * data[i-22]
1263         mov     ecx, [eax + 80]                 ; ecx =  qlp_coeff[20]
1264         imul    ecx, [edi - 84]                 ; ecx =  qlp_coeff[20] * data[i-21]
1265         add     ebp, ecx                        ; sum += qlp_coeff[20] * data[i-21]
1266         mov     ecx, [eax + 76]                 ; ecx =  qlp_coeff[19]
1267         imul    ecx, [edi - 80]                 ; ecx =  qlp_coeff[19] * data[i-20]
1268         add     ebp, ecx                        ; sum += qlp_coeff[19] * data[i-20]
1269         mov     ecx, [eax + 72]                 ; ecx =  qlp_coeff[18]
1270         imul    ecx, [edi - 76]                 ; ecx =  qlp_coeff[18] * data[i-19]
1271         add     ebp, ecx                        ; sum += qlp_coeff[18] * data[i-19]
1272         mov     ecx, [eax + 68]                 ; ecx =  qlp_coeff[17]
1273         imul    ecx, [edi - 72]                 ; ecx =  qlp_coeff[17] * data[i-18]
1274         add     ebp, ecx                        ; sum += qlp_coeff[17] * data[i-18]
1275         mov     ecx, [eax + 64]                 ; ecx =  qlp_coeff[16]
1276         imul    ecx, [edi - 68]                 ; ecx =  qlp_coeff[16] * data[i-17]
1277         add     ebp, ecx                        ; sum += qlp_coeff[16] * data[i-17]
1278         mov     ecx, [eax + 60]                 ; ecx =  qlp_coeff[15]
1279         imul    ecx, [edi - 64]                 ; ecx =  qlp_coeff[15] * data[i-16]
1280         add     ebp, ecx                        ; sum += qlp_coeff[15] * data[i-16]
1281         mov     ecx, [eax + 56]                 ; ecx =  qlp_coeff[14]
1282         imul    ecx, [edi - 60]                 ; ecx =  qlp_coeff[14] * data[i-15]
1283         add     ebp, ecx                        ; sum += qlp_coeff[14] * data[i-15]
1284         mov     ecx, [eax + 52]                 ; ecx =  qlp_coeff[13]
1285         imul    ecx, [edi - 56]                 ; ecx =  qlp_coeff[13] * data[i-14]
1286         add     ebp, ecx                        ; sum += qlp_coeff[13] * data[i-14]
1287         mov     ecx, [eax + 48]                 ; ecx =  qlp_coeff[12]
1288         imul    ecx, [edi - 52]                 ; ecx =  qlp_coeff[12] * data[i-13]
1289         add     ebp, ecx                        ; sum += qlp_coeff[12] * data[i-13]
1290         mov     ecx, [eax + 44]                 ; ecx =  qlp_coeff[11]
1291         imul    ecx, [edi - 48]                 ; ecx =  qlp_coeff[11] * data[i-12]
1292         add     ebp, ecx                        ; sum += qlp_coeff[11] * data[i-12]
1293         mov     ecx, [eax + 40]                 ; ecx =  qlp_coeff[10]
1294         imul    ecx, [edi - 44]                 ; ecx =  qlp_coeff[10] * data[i-11]
1295         add     ebp, ecx                        ; sum += qlp_coeff[10] * data[i-11]
1296         mov     ecx, [eax + 36]                 ; ecx =  qlp_coeff[ 9]
1297         imul    ecx, [edi - 40]                 ; ecx =  qlp_coeff[ 9] * data[i-10]
1298         add     ebp, ecx                        ; sum += qlp_coeff[ 9] * data[i-10]
1299         mov     ecx, [eax + 32]                 ; ecx =  qlp_coeff[ 8]
1300         imul    ecx, [edi - 36]                 ; ecx =  qlp_coeff[ 8] * data[i- 9]
1301         add     ebp, ecx                        ; sum += qlp_coeff[ 8] * data[i- 9]
1302         mov     ecx, [eax + 28]                 ; ecx =  qlp_coeff[ 7]
1303         imul    ecx, [edi - 32]                 ; ecx =  qlp_coeff[ 7] * data[i- 8]
1304         add     ebp, ecx                        ; sum += qlp_coeff[ 7] * data[i- 8]
1305         mov     ecx, [eax + 24]                 ; ecx =  qlp_coeff[ 6]
1306         imul    ecx, [edi - 28]                 ; ecx =  qlp_coeff[ 6] * data[i- 7]
1307         add     ebp, ecx                        ; sum += qlp_coeff[ 6] * data[i- 7]
1308         mov     ecx, [eax + 20]                 ; ecx =  qlp_coeff[ 5]
1309         imul    ecx, [edi - 24]                 ; ecx =  qlp_coeff[ 5] * data[i- 6]
1310         add     ebp, ecx                        ; sum += qlp_coeff[ 5] * data[i- 6]
1311         mov     ecx, [eax + 16]                 ; ecx =  qlp_coeff[ 4]
1312         imul    ecx, [edi - 20]                 ; ecx =  qlp_coeff[ 4] * data[i- 5]
1313         add     ebp, ecx                        ; sum += qlp_coeff[ 4] * data[i- 5]
1314         mov     ecx, [eax + 12]                 ; ecx =  qlp_coeff[ 3]
1315         imul    ecx, [edi - 16]                 ; ecx =  qlp_coeff[ 3] * data[i- 4]
1316         add     ebp, ecx                        ; sum += qlp_coeff[ 3] * data[i- 4]
1317         mov     ecx, [eax + 8]                  ; ecx =  qlp_coeff[ 2]
1318         imul    ecx, [edi - 12]                 ; ecx =  qlp_coeff[ 2] * data[i- 3]
1319         add     ebp, ecx                        ; sum += qlp_coeff[ 2] * data[i- 3]
1320         mov     ecx, [eax + 4]                  ; ecx =  qlp_coeff[ 1]
1321         imul    ecx, [edi - 8]                  ; ecx =  qlp_coeff[ 1] * data[i- 2]
1322         add     ebp, ecx                        ; sum += qlp_coeff[ 1] * data[i- 2]
1323         mov     ecx, [eax]                      ; ecx =  qlp_coeff[ 0] (NOTE: one byte missing from instruction)
1324         imul    ecx, [edi - 4]                  ; ecx =  qlp_coeff[ 0] * data[i- 1]
1325         add     ebp, ecx                        ; sum += qlp_coeff[ 0] * data[i- 1]
1326 .jumper_0:
1327
1328         mov     cl, [esp + 36]
1329         sar     ebp, cl                         ; ebp = (sum >> lp_quantization)
1330         add     ebp, [esi + edi]                ; ebp = residual[i] + (sum >> lp_quantization)
1331         mov     [edi], ebp                      ; data[i] = residual[i] + (sum >> lp_quantization)
1332         add     edi, byte 4
1333
1334         dec     ebx
1335         jz      short .end
1336         xor     ebp, ebp
1337         jmp     edx
1338
1339 .end:
1340         pop     edi
1341         pop     esi
1342         pop     ebx
1343         pop     ebp
1344         ret
1345
1346 ; WATCHOUT: this routine works on 16 bit data which means bits-per-sample for
1347 ; the channel must be <= 16.  Especially note that this routine cannot be used
1348 ; for side-channel coded 16bps channels since the effective bps is 17.
1349 ; WATCHOUT: this routine requires that each data array have a buffer of up to
1350 ; 3 zeroes in front (at negative indices) for alignment purposes, i.e. for each
1351 ; channel n, data[n][-1] through data[n][-3] should be accessible and zero.
1352         ALIGN   16
1353 cident FLAC__lpc_restore_signal_asm_ia32_mmx
1354         ;[esp + 40]     data[]
1355         ;[esp + 36]     lp_quantization
1356         ;[esp + 32]     order
1357         ;[esp + 28]     qlp_coeff[]
1358         ;[esp + 24]     data_len
1359         ;[esp + 20]     residual[]
1360
1361         ;ASSERT(order > 0)
1362
1363         push    ebp
1364         push    ebx
1365         push    esi
1366         push    edi
1367
1368         mov     esi, [esp + 20]
1369         mov     edi, [esp + 40]
1370         mov     eax, [esp + 32]
1371         mov     ebx, [esp + 24]
1372
1373         test    ebx, ebx
1374         jz      near .end                       ; do nothing if data_len == 0
1375         cmp     eax, byte 4
1376         jb      near FLAC__lpc_restore_signal_asm_ia32.begin
1377
1378         mov     edx, [esp + 28]
1379         movd    mm6, [esp + 36]
1380         mov     ebp, esp
1381
1382         and     esp, 0xfffffff8
1383
1384         xor     ecx, ecx
1385 .copy_qlp_loop:
1386         push    word [edx + 4 * ecx]
1387         inc     ecx
1388         cmp     ecx, eax
1389         jnz     short .copy_qlp_loop
1390
1391         and     ecx, 0x3
1392         test    ecx, ecx
1393         je      short .za_end
1394         sub     ecx, byte 4
1395 .za_loop:
1396         push    word 0
1397         inc     eax
1398         inc     ecx
1399         jnz     short .za_loop
1400 .za_end:
1401
1402         movq    mm5, [esp + 2 * eax - 8]
1403         movd    mm4, [edi - 16]
1404         punpckldq       mm4, [edi - 12]
1405         movd    mm0, [edi - 8]
1406         punpckldq       mm0, [edi - 4]
1407         packssdw        mm4, mm0
1408
1409         cmp     eax, byte 4
1410         jnbe    short .mmx_4more
1411
1412         align   16
1413 .mmx_4_loop_i:
1414         movq    mm7, mm4
1415         pmaddwd mm7, mm5
1416         movq    mm0, mm7
1417         punpckhdq       mm7, mm7
1418         paddd   mm7, mm0
1419         psrad   mm7, mm6
1420         movd    mm1, [esi]
1421         paddd   mm7, mm1
1422         movd    [edi], mm7
1423         psllq   mm7, 48
1424         psrlq   mm4, 16
1425         por     mm4, mm7
1426
1427         add     esi, byte 4
1428         add     edi, byte 4
1429
1430         dec     ebx
1431         jnz     .mmx_4_loop_i
1432         jmp     .mmx_end
1433 .mmx_4more:
1434         shl     eax, 2
1435         neg     eax
1436         add     eax, byte 16
1437         align   16
1438 .mmx_4more_loop_i:
1439         mov     ecx, edi
1440         add     ecx, eax
1441         mov     edx, esp
1442
1443         movq    mm7, mm4
1444         pmaddwd mm7, mm5
1445
1446         align   16
1447 .mmx_4more_loop_j:
1448         movd    mm0, [ecx - 16]
1449         punpckldq       mm0, [ecx - 12]
1450         movd    mm1, [ecx - 8]
1451         punpckldq       mm1, [ecx - 4]
1452         packssdw        mm0, mm1
1453         pmaddwd mm0, [edx]
1454         paddd   mm7, mm0
1455
1456         add     edx, byte 8
1457         add     ecx, byte 16
1458         cmp     ecx, edi
1459         jnz     .mmx_4more_loop_j
1460
1461         movq    mm0, mm7
1462         punpckhdq       mm7, mm7
1463         paddd   mm7, mm0
1464         psrad   mm7, mm6
1465         movd    mm1, [esi]
1466         paddd   mm7, mm1
1467         movd    [edi], mm7
1468         psllq   mm7, 48
1469         psrlq   mm4, 16
1470         por     mm4, mm7
1471
1472         add     esi, byte 4
1473         add     edi, byte 4
1474
1475         dec     ebx
1476         jnz     short .mmx_4more_loop_i
1477 .mmx_end:
1478         emms
1479         mov     esp, ebp
1480
1481 .end:
1482         pop     edi
1483         pop     esi
1484         pop     ebx
1485         pop     ebp
1486         ret
1487
1488 end