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