caa9e2964015fa4aaabcb1595fdf8a3921406027
[flac.git] / src / libFLAC / ia32 / lpc_asm-unrolled.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-2014  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 ; [CR] is a note to flag that the instruction can be easily reordered
35
36 %include "nasm.h"
37
38         data_section
39
40 cglobal FLAC__lpc_compute_autocorrelation_asm
41
42         code_section
43
44 ; **********************************************************************
45 ;
46 ; void FLAC__lpc_compute_autocorrelation_asm(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[])
47 ; {
48 ;       FLAC__real d;
49 ;       unsigned sample, coeff;
50 ;       const unsigned limit = data_len - lag;
51 ;
52 ;       assert(lag > 0);
53 ;       assert(lag <= data_len);
54 ;
55 ;       for(coeff = 0; coeff < lag; coeff++)
56 ;               autoc[coeff] = 0.0;
57 ;       for(sample = 0; sample <= limit; sample++){
58 ;               d = data[sample];
59 ;               for(coeff = 0; coeff < lag; coeff++)
60 ;                       autoc[coeff] += d * data[sample+coeff];
61 ;       }
62 ;       for(; sample < data_len; sample++){
63 ;               d = data[sample];
64 ;               for(coeff = 0; coeff < data_len - sample; coeff++)
65 ;                       autoc[coeff] += d * data[sample+coeff];
66 ;       }
67 ; }
68 ;
69 FLAC__lpc_compute_autocorrelation_asm:
70
71         push    ebp
72         lea     ebp, [esp + 8]
73         push    ebx
74         push    esi
75         push    edi
76
77         mov     edx, [ebp + 8]                  ; edx == lag
78         mov     ecx, [ebp + 4]                  ; ecx == data_len
79         mov     esi, [ebp]                      ; esi == data
80         mov     edi, [ebp + 12]                 ; edi == autoc
81
82         cmp     edx, 1
83         ja      short .lag_above_1
84 .lag_eq_1:
85         fldz                                    ; will accumulate autoc[0]
86         ALIGN 16
87 .lag_1_loop:
88         fld     dword [esi]
89         add     esi, byte 4                     ; sample++
90         fmul    st0, st0
91         faddp   st1, st0
92         dec     ecx
93         jnz     .lag_1_loop
94         fstp    dword [edi]
95         jmp     .end
96
97 .lag_above_1:
98         cmp     edx, 2
99         ja      short .lag_above_2
100 .lag_eq_2:
101         fldz                                    ; will accumulate autoc[1]
102         dec     ecx
103         fldz                                    ; will accumulate autoc[0]
104         fld     dword [esi]
105         ALIGN 16
106 .lag_2_loop:
107         add     esi, byte 4                     ; [CR] sample++
108         fld     st0
109         fmul    st0, st0
110         faddp   st2, st0                        ; add to autoc[0]
111         fld     dword [esi]
112         fmul    st1, st0
113         fxch
114         faddp   st3, st0                        ; add to autoc[1]
115         dec     ecx
116         jnz     .lag_2_loop
117         ; clean up the leftovers
118         fmul    st0, st0
119         faddp   st1, st0                        ; add to autoc[0]
120         fstp    dword [edi]
121         fstp    dword [edi + 4]
122         jmp     .end
123
124 .lag_above_2:
125         cmp     edx, 3
126         ja      short .lag_above_3
127 .lag_eq_3:
128         fldz                                    ; will accumulate autoc[2]
129         dec     ecx
130         fldz                                    ; will accumulate autoc[1]
131         dec     ecx
132         fldz                                    ; will accumulate autoc[0]
133         ALIGN 16
134 .lag_3_loop:
135         fld     dword [esi]
136         fld     st0
137         fmul    st0, st0
138         faddp   st2, st0                        ; add to autoc[0]
139         fld     dword [esi + 4]
140         fmul    st0, st1
141         faddp   st3, st0                        ; add to autoc[1]
142         fld     dword [esi + 8]
143         fmulp   st1, st0
144         add     esi, byte 4                     ; [CR] sample++
145         faddp   st3, st0                        ; add to autoc[2]
146         dec     ecx
147         jnz     .lag_3_loop
148         ; clean up the leftovers
149         fld     dword [esi]
150         fld     st0
151         fmul    st0, st0
152         faddp   st2, st0                        ; add to autoc[0]
153         fld     dword [esi + 4]
154         fmul    st1, st0
155         fxch
156         faddp   st3, st0                        ; add to autoc[1]
157         fmul    st0, st0
158         faddp   st1, st0                        ; add to autoc[0]
159         fstp    dword [edi]
160         fstp    dword [edi + 4]
161         fstp    dword [edi + 8]
162         jmp     .end
163
164 .lag_above_3:
165         cmp     edx, 4
166         ja      near .lag_above_4
167 .lag_eq_4:
168         fldz                                    ; will accumulate autoc[3]
169         dec     ecx
170         fldz                                    ; will accumulate autoc[2]
171         dec     ecx
172         fldz                                    ; will accumulate autoc[1]
173         dec     ecx
174         fldz                                    ; will accumulate autoc[0]
175         ALIGN 16
176 .lag_4_loop:
177         fld     dword [esi]
178         fld     st0
179         fmul    st0, st0
180         faddp   st2, st0                        ; add to autoc[0]
181         fld     dword [esi + 4]
182         fmul    st0, st1
183         faddp   st3, st0                        ; add to autoc[1]
184         fld     dword [esi + 8]
185         fmul    st0, st1
186         faddp   st4, st0                        ; add to autoc[2]
187         fld     dword [esi + 12]
188         fmulp   st1, st0
189         add     esi, byte 4                     ; [CR] sample++
190         faddp   st4, st0                        ; add to autoc[3]
191         dec     ecx
192         jnz     .lag_4_loop
193         ; clean up the leftovers
194         fld     dword [esi]
195         fld     st0
196         fmul    st0, st0
197         faddp   st2, st0                        ; add to autoc[0]
198         fld     dword [esi + 4]
199         fmul    st0, st1
200         faddp   st3, st0                        ; add to autoc[1]
201         fld     dword [esi + 8]
202         fmulp   st1, st0
203         add     esi, byte 4                     ; [CR] sample++
204         faddp   st3, st0                        ; add to autoc[2]
205         fld     dword [esi]
206         fld     st0
207         fmul    st0, st0
208         faddp   st2, st0                        ; add to autoc[0]
209         fld     dword [esi + 4]
210         fmul    st1, st0
211         fxch
212         faddp   st3, st0                        ; add to autoc[1]
213         fmul    st0, st0
214         faddp   st1, st0                        ; add to autoc[0]
215         fstp    dword [edi]
216         fstp    dword [edi + 4]
217         fstp    dword [edi + 8]
218         fstp    dword [edi + 12]
219         jmp     .end
220
221 .lag_above_4:
222         cmp     edx, 5
223         ja      near .lag_above_5
224 .lag_eq_5:
225         fldz                                    ; will accumulate autoc[4]
226         fldz                                    ; will accumulate autoc[3]
227         fldz                                    ; will accumulate autoc[2]
228         fldz                                    ; will accumulate autoc[1]
229         fldz                                    ; will accumulate autoc[0]
230         sub     ecx, byte 4
231         ALIGN 16
232 .lag_5_loop:
233         fld     dword [esi]
234         fld     st0
235         fmul    st0, st0
236         faddp   st2, st0                        ; add to autoc[0]
237         fld     dword [esi + 4]
238         fmul    st0, st1
239         faddp   st3, st0                        ; add to autoc[1]
240         fld     dword [esi + 8]
241         fmul    st0, st1
242         faddp   st4, st0                        ; add to autoc[2]
243         fld     dword [esi + 12]
244         fmul    st0, st1
245         faddp   st5, st0                        ; add to autoc[3]
246         fld     dword [esi + 16]
247         fmulp   st1, st0
248         add     esi, byte 4                     ; [CR] sample++
249         faddp   st5, st0                        ; add to autoc[4]
250         dec     ecx
251         jnz     .lag_5_loop
252         ; clean up the leftovers
253         fld     dword [esi]
254         fld     st0
255         fmul    st0, st0
256         faddp   st2, st0                        ; add to autoc[0]
257         fld     dword [esi + 4]
258         fmul    st0, st1
259         faddp   st3, st0                        ; add to autoc[1]
260         fld     dword [esi + 8]
261         fmul    st0, st1
262         faddp   st4, st0                        ; add to autoc[2]
263         fld     dword [esi + 12]
264         fmulp   st1, st0
265         add     esi, byte 4                     ; [CR] sample++
266         faddp   st4, st0                        ; add to autoc[3]
267         fld     dword [esi]
268         fld     st0
269         fmul    st0, st0
270         faddp   st2, st0                        ; add to autoc[0]
271         fld     dword [esi + 4]
272         fmul    st0, st1
273         faddp   st3, st0                        ; add to autoc[1]
274         fld     dword [esi + 8]
275         fmulp   st1, st0
276         add     esi, byte 4                     ; [CR] sample++
277         faddp   st3, st0                        ; add to autoc[2]
278         fld     dword [esi]
279         fld     st0
280         fmul    st0, st0
281         faddp   st2, st0                        ; add to autoc[0]
282         fld     dword [esi + 4]
283         fmul    st1, st0
284         fxch
285         faddp   st3, st0                        ; add to autoc[1]
286         fmul    st0, st0
287         faddp   st1, st0                        ; add to autoc[0]
288         fstp    dword [edi]
289         fstp    dword [edi + 4]
290         fstp    dword [edi + 8]
291         fstp    dword [edi + 12]
292         fstp    dword [edi + 16]
293         jmp     .end
294
295 .lag_above_5:
296         cmp     edx, 6
297         ja      .lag_above_6
298 .lag_eq_6:
299         fldz                                    ; will accumulate autoc[5]
300         fldz                                    ; will accumulate autoc[4]
301         fldz                                    ; will accumulate autoc[3]
302         fldz                                    ; will accumulate autoc[2]
303         fldz                                    ; will accumulate autoc[1]
304         fldz                                    ; will accumulate autoc[0]
305         sub     ecx, byte 5
306         ALIGN 16
307 .lag_6_loop:
308         fld     dword [esi]
309         fld     st0
310         fmul    st0, st0
311         faddp   st2, st0                        ; add to autoc[0]
312         fld     dword [esi + 4]
313         fmul    st0, st1
314         faddp   st3, st0                        ; add to autoc[1]
315         fld     dword [esi + 8]
316         fmul    st0, st1
317         faddp   st4, st0                        ; add to autoc[2]
318         fld     dword [esi + 12]
319         fmul    st0, st1
320         faddp   st5, st0                        ; add to autoc[3]
321         fld     dword [esi + 16]
322         fmul    st0, st1
323         faddp   st6, st0                        ; add to autoc[4]
324         fld     dword [esi + 20]
325         fmulp   st1, st0
326         add     esi, byte 4                     ; [CR] sample++
327         faddp   st6, st0                        ; add to autoc[5]
328         dec     ecx
329         jnz     .lag_6_loop
330         ; clean up the leftovers
331         fld     dword [esi]
332         fld     st0
333         fmul    st0, st0
334         faddp   st2, st0                        ; add to autoc[0]
335         fld     dword [esi + 4]
336         fmul    st0, st1
337         faddp   st3, st0                        ; add to autoc[1]
338         fld     dword [esi + 8]
339         fmul    st0, st1
340         faddp   st4, st0                        ; add to autoc[2]
341         fld     dword [esi + 12]
342         fmul    st0, st1
343         faddp   st5, st0                        ; add to autoc[3]
344         fld     dword [esi + 16]
345         fmulp   st1, st0
346         add     esi, byte 4                     ; [CR] sample++
347         faddp   st5, st0                        ; add to autoc[4]
348         fld     dword [esi]
349         fld     st0
350         fmul    st0, st0
351         faddp   st2, st0                        ; add to autoc[0]
352         fld     dword [esi + 4]
353         fmul    st0, st1
354         faddp   st3, st0                        ; add to autoc[1]
355         fld     dword [esi + 8]
356         fmul    st0, st1
357         faddp   st4, st0                        ; add to autoc[2]
358         fld     dword [esi + 12]
359         fmulp   st1, st0
360         add     esi, byte 4                     ; [CR] sample++
361         faddp   st4, st0                        ; add to autoc[3]
362         fld     dword [esi]
363         fld     st0
364         fmul    st0, st0
365         faddp   st2, st0                        ; add to autoc[0]
366         fld     dword [esi + 4]
367         fmul    st0, st1
368         faddp   st3, st0                        ; add to autoc[1]
369         fld     dword [esi + 8]
370         fmulp   st1, st0
371         add     esi, byte 4                     ; [CR] sample++
372         faddp   st3, st0                        ; add to autoc[2]
373         fld     dword [esi]
374         fld     st0
375         fmul    st0, st0
376         faddp   st2, st0                        ; add to autoc[0]
377         fld     dword [esi + 4]
378         fmul    st1, st0
379         fxch
380         faddp   st3, st0                        ; add to autoc[1]
381         fmul    st0, st0
382         faddp   st1, st0                        ; add to autoc[0]
383         fstp    dword [edi]
384         fstp    dword [edi + 4]
385         fstp    dword [edi + 8]
386         fstp    dword [edi + 12]
387         fstp    dword [edi + 16]
388         fstp    dword [edi + 20]
389         jmp     .end
390
391 .lag_above_6:
392         ;       for(coeff = 0; coeff < lag; coeff++)
393         ;               autoc[coeff] = 0.0;
394         lea     ecx, [edx * 2]                  ; ecx = # of dwords of 0 to write
395         xor     eax, eax
396         rep     stosd
397         mov     ecx, [ebp + 4]                  ; ecx == data_len
398         mov     edi, [ebp + 12]                 ; edi == autoc
399         ;       const unsigned limit = data_len - lag;
400         sub     ecx, edx
401         inc     ecx                             ; we are looping <= limit so we add one to the counter
402         ;       for(sample = 0; sample <= limit; sample++){
403         ;               d = data[sample];
404         ;               for(coeff = 0; coeff < lag; coeff++)
405         ;                       autoc[coeff] += d * data[sample+coeff];
406         ;       }
407         xor     eax, eax                        ; eax == sample <- 0
408         ALIGN 16
409 .outer_loop:
410         push    eax                             ; save sample
411         fld     dword [esi + eax * 4]           ; ST = d <- data[sample]
412         mov     ebx, eax                        ; ebx == sample+coeff <- sample
413         mov     edx, [ebp + 8]                  ; edx <- lag
414         xor     eax, eax                        ; eax == coeff <- 0
415         ALIGN 16
416 .inner_loop:
417         fld     st0                             ; ST = d d
418         fmul    dword [esi + ebx * 4]           ; ST = d*data[sample+coeff] d
419         fadd    dword [edi + eax * 4]           ; ST = autoc[coeff]+d*data[sample+coeff] d
420         fstp    dword [edi + eax * 4]           ; autoc[coeff]+=d*data[sample+coeff]  ST = d
421         inc     ebx                             ; (sample+coeff)++
422         inc     eax                             ; coeff++
423         dec     edx
424         jnz     .inner_loop
425         pop     eax                             ; restore sample
426         fstp    st0                             ; pop d, ST = empty
427         inc     eax                             ; sample++
428         loop    .outer_loop
429         ;       for(; sample < data_len; sample++){
430         ;               d = data[sample];
431         ;               for(coeff = 0; coeff < data_len - sample; coeff++)
432         ;                       autoc[coeff] += d * data[sample+coeff];
433         ;       }
434         mov     ecx, [ebp + 8]                  ; ecx <- lag
435         dec     ecx                             ; ecx <- lag - 1
436         jz      .outer_end                      ; skip loop if 0
437 .outer_loop2:
438         push    eax                             ; save sample
439         fld     dword [esi + eax * 4]           ; ST = d <- data[sample]
440         mov     ebx, eax                        ; ebx == sample+coeff <- sample
441         mov     edx, [ebp + 4]                  ; edx <- data_len
442         sub     edx, eax                        ; edx <- data_len-sample
443         xor     eax, eax                        ; eax == coeff <- 0
444 .inner_loop2:
445         fld     st0                             ; ST = d d
446         fmul    dword [esi + ebx * 4]           ; ST = d*data[sample+coeff] d
447         fadd    dword [edi + eax * 4]           ; ST = autoc[coeff]+d*data[sample+coeff] d
448         fstp    dword [edi + eax * 4]           ; autoc[coeff]+=d*data[sample+coeff]  ST = d
449         inc     ebx                             ; (sample+coeff)++
450         inc     eax                             ; coeff++
451         dec     edx
452         jnz     .inner_loop2
453         pop     eax                             ; restore sample
454         fstp    st0                             ; pop d, ST = empty
455         inc     eax                             ; sample++
456         loop    .outer_loop2
457 .outer_end:
458         jmp     .end
459
460 .lag_eq_6_plus_1:
461         mov     ecx, [ebp + 4]                  ; ecx == data_len
462         mov     esi, [ebp]                      ; esi == data
463         mov     edi, [ebp + 12]                 ; edi == autoc
464         fldz                                    ; will accumulate autoc[6]
465         sub     ecx, byte 6
466         ALIGN 16
467 .lag_6_1_loop:
468         fld     dword [esi]
469         fld     dword [esi + 24]
470         fmulp   st1, st0
471         add     esi, byte 4                     ; [CR] sample++
472         faddp   st1, st0                        ; add to autoc[6]
473         dec     ecx
474         jnz     .lag_6_1_loop
475         fstp    dword [edi + 24]
476         jmp     .end
477
478 .lag_eq_6_plus_2:
479         mov     ecx, [ebp + 4]                  ; ecx == data_len
480         mov     esi, [ebp]                      ; esi == data
481         mov     edi, [ebp + 12]                 ; edi == autoc
482         fldz                                    ; will accumulate autoc[7]
483         fldz                                    ; will accumulate autoc[6]
484         sub     ecx, byte 7
485         ALIGN 16
486 .lag_6_2_loop:
487         fld     dword [esi]
488         fld     dword [esi + 24]
489         fmul    st0, st1
490         faddp   st2, st0                        ; add to autoc[6]
491         fld     dword [esi + 28]
492         fmulp   st1, st0
493         add     esi, byte 4                     ; [CR] sample++
494         faddp   st2, st0                        ; add to autoc[7]
495         dec     ecx
496         jnz     .lag_6_2_loop
497         ; clean up the leftovers
498         fld     dword [esi]
499         fld     dword [esi + 24]
500         fmulp   st1, st0
501         faddp   st1, st0                        ; add to autoc[6]
502         fstp    dword [edi + 24]
503         fstp    dword [edi + 28]
504         jmp     .end
505
506 .lag_eq_6_plus_3:
507         mov     ecx, [ebp + 4]                  ; ecx == data_len
508         mov     esi, [ebp]                      ; esi == data
509         mov     edi, [ebp + 12]                 ; edi == autoc
510         fldz                                    ; will accumulate autoc[8]
511         fldz                                    ; will accumulate autoc[7]
512         fldz                                    ; will accumulate autoc[6]
513         sub     ecx, byte 8
514         ALIGN 16
515 .lag_6_3_loop:
516         fld     dword [esi]
517         fld     dword [esi + 24]
518         fmul    st0, st1
519         faddp   st2, st0                        ; add to autoc[6]
520         fld     dword [esi + 28]
521         fmul    st0, st1
522         faddp   st3, st0                        ; add to autoc[7]
523         fld     dword [esi + 32]
524         fmulp   st1, st0
525         add     esi, byte 4                     ; [CR] sample++
526         faddp   st3, st0                        ; add to autoc[8]
527         dec     ecx
528         jnz     .lag_6_3_loop
529         ; clean up the leftovers
530         fld     dword [esi]
531         fld     dword [esi + 24]
532         fmul    st0, st1
533         faddp   st2, st0                        ; add to autoc[6]
534         fld     dword [esi + 28]
535         fmulp   st1, st0
536         add     esi, byte 4                     ; [CR] sample++
537         faddp   st2, st0                        ; add to autoc[7]
538         fld     dword [esi]
539         fld     dword [esi + 24]
540         fmulp   st1, st0
541         faddp   st1, st0                        ; add to autoc[6]
542         fstp    dword [edi + 24]
543         fstp    dword [edi + 28]
544         fstp    dword [edi + 32]
545         jmp     .end
546
547 .lag_eq_6_plus_4:
548         mov     ecx, [ebp + 4]                  ; ecx == data_len
549         mov     esi, [ebp]                      ; esi == data
550         mov     edi, [ebp + 12]                 ; edi == autoc
551         fldz                                    ; will accumulate autoc[9]
552         fldz                                    ; will accumulate autoc[8]
553         fldz                                    ; will accumulate autoc[7]
554         fldz                                    ; will accumulate autoc[6]
555         sub     ecx, byte 9
556         ALIGN 16
557 .lag_6_4_loop:
558         fld     dword [esi]
559         fld     dword [esi + 24]
560         fmul    st0, st1
561         faddp   st2, st0                        ; add to autoc[6]
562         fld     dword [esi + 28]
563         fmul    st0, st1
564         faddp   st3, st0                        ; add to autoc[7]
565         fld     dword [esi + 32]
566         fmul    st0, st1
567         faddp   st4, st0                        ; add to autoc[8]
568         fld     dword [esi + 36]
569         fmulp   st1, st0
570         add     esi, byte 4                     ; [CR] sample++
571         faddp   st4, st0                        ; add to autoc[9]
572         dec     ecx
573         jnz     .lag_6_4_loop
574         ; clean up the leftovers
575         fld     dword [esi]
576         fld     dword [esi + 24]
577         fmul    st0, st1
578         faddp   st2, st0                        ; add to autoc[6]
579         fld     dword [esi + 28]
580         fmul    st0, st1
581         faddp   st3, st0                        ; add to autoc[7]
582         fld     dword [esi + 32]
583         fmulp   st1, st0
584         add     esi, byte 4                     ; [CR] sample++
585         faddp   st3, st0                        ; add to autoc[8]
586         fld     dword [esi]
587         fld     dword [esi + 24]
588         fmul    st0, st1
589         faddp   st2, st0                        ; add to autoc[6]
590         fld     dword [esi + 28]
591         fmulp   st1, st0
592         add     esi, byte 4                     ; [CR] sample++
593         faddp   st2, st0                        ; add to autoc[7]
594         fld     dword [esi]
595         fld     dword [esi + 24]
596         fmulp   st1, st0
597         faddp   st1, st0                        ; add to autoc[6]
598         fstp    dword [edi + 24]
599         fstp    dword [edi + 28]
600         fstp    dword [edi + 32]
601         fstp    dword [edi + 36]
602         jmp     .end
603
604 .lag_eq_6_plus_5:
605         mov     ecx, [ebp + 4]                  ; ecx == data_len
606         mov     esi, [ebp]                      ; esi == data
607         mov     edi, [ebp + 12]                 ; edi == autoc
608         fldz                                    ; will accumulate autoc[10]
609         fldz                                    ; will accumulate autoc[9]
610         fldz                                    ; will accumulate autoc[8]
611         fldz                                    ; will accumulate autoc[7]
612         fldz                                    ; will accumulate autoc[6]
613         sub     ecx, byte 10
614         ALIGN 16
615 .lag_6_5_loop:
616         fld     dword [esi]
617         fld     dword [esi + 24]
618         fmul    st0, st1
619         faddp   st2, st0                        ; add to autoc[6]
620         fld     dword [esi + 28]
621         fmul    st0, st1
622         faddp   st3, st0                        ; add to autoc[7]
623         fld     dword [esi + 32]
624         fmul    st0, st1
625         faddp   st4, st0                        ; add to autoc[8]
626         fld     dword [esi + 36]
627         fmul    st0, st1
628         faddp   st5, st0                        ; add to autoc[9]
629         fld     dword [esi + 40]
630         fmulp   st1, st0
631         add     esi, byte 4                     ; [CR] sample++
632         faddp   st5, st0                        ; add to autoc[10]
633         dec     ecx
634         jnz     .lag_6_5_loop
635         ; clean up the leftovers
636         fld     dword [esi]
637         fld     dword [esi + 24]
638         fmul    st0, st1
639         faddp   st2, st0                        ; add to autoc[6]
640         fld     dword [esi + 28]
641         fmul    st0, st1
642         faddp   st3, st0                        ; add to autoc[7]
643         fld     dword [esi + 32]
644         fmul    st0, st1
645         faddp   st4, st0                        ; add to autoc[8]
646         fld     dword [esi + 36]
647         fmulp   st1, st0
648         add     esi, byte 4                     ; [CR] sample++
649         faddp   st4, st0                        ; add to autoc[9]
650         fld     dword [esi]
651         fld     dword [esi + 24]
652         fmul    st0, st1
653         faddp   st2, st0                        ; add to autoc[6]
654         fld     dword [esi + 28]
655         fmul    st0, st1
656         faddp   st3, st0                        ; add to autoc[7]
657         fld     dword [esi + 32]
658         fmulp   st1, st0
659         add     esi, byte 4                     ; [CR] sample++
660         faddp   st3, st0                        ; add to autoc[8]
661         fld     dword [esi]
662         fld     dword [esi + 24]
663         fmul    st0, st1
664         faddp   st2, st0                        ; add to autoc[6]
665         fld     dword [esi + 28]
666         fmulp   st1, st0
667         add     esi, byte 4                     ; [CR] sample++
668         faddp   st2, st0                        ; add to autoc[7]
669         fld     dword [esi]
670         fld     dword [esi + 24]
671         fmulp   st1, st0
672         faddp   st1, st0                        ; add to autoc[6]
673         fstp    dword [edi + 24]
674         fstp    dword [edi + 28]
675         fstp    dword [edi + 32]
676         fstp    dword [edi + 36]
677         fstp    dword [edi + 40]
678         jmp     .end
679
680 .lag_eq_6_plus_6:
681         mov     ecx, [ebp + 4]                  ; ecx == data_len
682         mov     esi, [ebp]                      ; esi == data
683         mov     edi, [ebp + 12]                 ; edi == autoc
684         fldz                                    ; will accumulate autoc[11]
685         fldz                                    ; will accumulate autoc[10]
686         fldz                                    ; will accumulate autoc[9]
687         fldz                                    ; will accumulate autoc[8]
688         fldz                                    ; will accumulate autoc[7]
689         fldz                                    ; will accumulate autoc[6]
690         sub     ecx, byte 11
691         ALIGN 16
692 .lag_6_6_loop:
693         fld     dword [esi]
694         fld     dword [esi + 24]
695         fmul    st0, st1
696         faddp   st2, st0                        ; add to autoc[6]
697         fld     dword [esi + 28]
698         fmul    st0, st1
699         faddp   st3, st0                        ; add to autoc[7]
700         fld     dword [esi + 32]
701         fmul    st0, st1
702         faddp   st4, st0                        ; add to autoc[8]
703         fld     dword [esi + 36]
704         fmul    st0, st1
705         faddp   st5, st0                        ; add to autoc[9]
706         fld     dword [esi + 40]
707         fmul    st0, st1
708         faddp   st6, st0                        ; add to autoc[10]
709         fld     dword [esi + 44]
710         fmulp   st1, st0
711         add     esi, byte 4                     ; [CR] sample++
712         faddp   st6, st0                        ; add to autoc[11]
713         dec     ecx
714         jnz     .lag_6_6_loop
715         ; clean up the leftovers
716         fld     dword [esi]
717         fld     dword [esi + 24]
718         fmul    st0, st1
719         faddp   st2, st0                        ; add to autoc[6]
720         fld     dword [esi + 28]
721         fmul    st0, st1
722         faddp   st3, st0                        ; add to autoc[7]
723         fld     dword [esi + 32]
724         fmul    st0, st1
725         faddp   st4, st0                        ; add to autoc[8]
726         fld     dword [esi + 36]
727         fmul    st0, st1
728         faddp   st5, st0                        ; add to autoc[9]
729         fld     dword [esi + 40]
730         fmulp   st1, st0
731         add     esi, byte 4                     ; [CR] sample++
732         faddp   st5, st0                        ; add to autoc[10]
733         fld     dword [esi]
734         fld     dword [esi + 24]
735         fmul    st0, st1
736         faddp   st2, st0                        ; add to autoc[6]
737         fld     dword [esi + 28]
738         fmul    st0, st1
739         faddp   st3, st0                        ; add to autoc[7]
740         fld     dword [esi + 32]
741         fmul    st0, st1
742         faddp   st4, st0                        ; add to autoc[8]
743         fld     dword [esi + 36]
744         fmulp   st1, st0
745         add     esi, byte 4                     ; [CR] sample++
746         faddp   st4, st0                        ; add to autoc[9]
747         fld     dword [esi]
748         fld     dword [esi + 24]
749         fmul    st0, st1
750         faddp   st2, st0                        ; add to autoc[6]
751         fld     dword [esi + 28]
752         fmul    st0, st1
753         faddp   st3, st0                        ; add to autoc[7]
754         fld     dword [esi + 32]
755         fmulp   st1, st0
756         add     esi, byte 4                     ; [CR] sample++
757         faddp   st3, st0                        ; add to autoc[8]
758         fld     dword [esi]
759         fld     dword [esi + 24]
760         fmul    st0, st1
761         faddp   st2, st0                        ; add to autoc[6]
762         fld     dword [esi + 28]
763         fmulp   st1, st0
764         add     esi, byte 4                     ; [CR] sample++
765         faddp   st2, st0                        ; add to autoc[7]
766         fld     dword [esi]
767         fld     dword [esi + 24]
768         fmulp   st1, st0
769         faddp   st1, st0                        ; add to autoc[6]
770         fstp    dword [edi + 24]
771         fstp    dword [edi + 28]
772         fstp    dword [edi + 32]
773         fstp    dword [edi + 36]
774         fstp    dword [edi + 40]
775         fstp    dword [edi + 44]
776         jmp     .end
777
778 .end:
779         pop     edi
780         pop     esi
781         pop     ebx
782         pop     ebp
783         ret
784
785 ; end