ba2fc3ccf3070e99f0a0b6b023a6518620b27de9
[platform/upstream/flac.git] / src / libFLAC / ia32 / bitreader_asm.nasm
1 ;  vim:filetype=nasm ts=8
2
3 ;  libFLAC - Free Lossless Audio Codec library
4 ;  Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008  Josh Coalson
5 ;
6 ;  Redistribution and use in source and binary forms, with or without
7 ;  modification, are permitted provided that the following conditions
8 ;  are met:
9 ;
10 ;  - Redistributions of source code must retain the above copyright
11 ;  notice, this list of conditions and the following disclaimer.
12 ;
13 ;  - Redistributions in binary form must reproduce the above copyright
14 ;  notice, this list of conditions and the following disclaimer in the
15 ;  documentation and/or other materials provided with the distribution.
16 ;
17 ;  - Neither the name of the Xiph.org Foundation nor the names of its
18 ;  contributors may be used to endorse or promote products derived from
19 ;  this software without specific prior written permission.
20 ;
21 ;  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ;  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 ;  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 ;  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
25 ;  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 ;  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 ;  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 ;  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 ;  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 ;  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 ;  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 %include "nasm.h"
34
35         data_section
36
37 cextern FLAC__crc16_table               ; unsigned FLAC__crc16_table[256];
38 cextern bitreader_read_from_client_     ; FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br);
39
40 cglobal FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap
41
42         code_section
43
44
45 ; **********************************************************************
46 ;
47 ; void FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter)
48 ;
49 ; Some details like assertions and other checking is performed by the caller.
50         ALIGN 16
51 cident FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap
52
53         ;ASSERT(0 != br);
54         ;ASSERT(0 != br->buffer);
55         ; WATCHOUT: code only works if sizeof(brword)==32; we can make things much faster with this assertion
56         ;ASSERT(FLAC__BITS_PER_WORD == 32);
57         ;ASSERT(parameter < 32);
58         ; the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it
59
60         ;; peppered throughout the code at major checkpoints are keys like this as to where things are at that point in time
61         ;; [esp + 16]   unsigned parameter
62         ;; [esp + 12]   unsigned nvals
63         ;; [esp + 8]    int vals[]
64         ;; [esp + 4]    FLAC__BitReader *br
65         mov     eax, [esp + 12]         ; if(nvals == 0)
66         test    eax, eax
67         ja      .nvals_gt_0
68         mov     eax, 1                  ;   return true;
69         ret
70
71 .nvals_gt_0:
72         push    ebp
73         push    ebx
74         push    esi
75         push    edi
76         sub     esp, 4
77         ;; [esp + 36]   unsigned parameter
78         ;; [esp + 32]   unsigned nvals
79         ;; [esp + 28]   int vals[]
80         ;; [esp + 24]   FLAC__BitReader *br
81         ;; [esp]        ucbits
82         mov     ebp, [esp + 24]         ; ebp <- br == br->buffer
83         mov     esi, [ebp + 16]         ; esi <- br->consumed_words (aka 'cwords' in the C version)
84         mov     ecx, [ebp + 20]         ; ecx <- br->consumed_bits  (aka 'cbits'  in the C version)
85         xor     edi, edi                ; edi <- 0  'uval'
86         ;; ecx          cbits
87         ;; esi          cwords
88         ;; edi          uval
89         ;; ebp          br
90         ;; [ebp]        br->buffer
91         ;; [ebp + 8]    br->words
92         ;; [ebp + 12]   br->bytes
93         ;; [ebp + 16]   br->consumed_words
94         ;; [ebp + 20]   br->consumed_bits
95         ;; [ebp + 24]   br->read_crc
96         ;; [ebp + 28]   br->crc16_align
97
98                                         ; ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits;
99         mov     eax, [ebp + 8]          ;   eax <- br->words
100         sub     eax, esi                ;   eax <- br->words-cwords
101         shl     eax, 2                  ;   eax <- (br->words-cwords)*FLAC__BYTES_PER_WORD
102         add     eax, [ebp + 12]         ;   eax <- (br->words-cwords)*FLAC__BYTES_PER_WORD + br->bytes
103         shl     eax, 3                  ;   eax <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8
104         sub     eax, ecx                ;   eax <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits
105         mov     [esp], eax              ;   ucbits <- eax
106
107         ALIGN 16
108 .val_loop:                              ; while(1) {
109
110         ;
111         ; read unary part
112         ;
113 .unary_loop:                            ;   while(1) {
114         ;; ecx          cbits
115         ;; esi          cwords
116         ;; edi          uval
117         ;; ebp          br
118         cmp     esi, [ebp + 8]          ;     while(cwords < br->words)   /* if we've not consumed up to a partial tail word... */
119         jae     near .c1_next1
120 .c1_loop:                               ;     {
121         mov     ebx, [ebp]
122         mov     eax, [ebx + 4*esi]      ;       b = br->buffer[cwords]
123         mov     edx, eax                ;       edx = br->buffer[cwords] (saved for later use)
124         shl     eax, cl                 ;       b = br->buffer[cwords] << cbits
125         test    eax, eax                ;         (still have to test since cbits may be 0, thus ZF not updated for shl eax,0)
126         jz      near .c1_next2          ;       if(b) {
127         bsr     ebx, eax
128         not     ebx
129         and     ebx, 31                 ;         ebx = 'i' = # of leading 0 bits in 'b' (eax)
130         add     ecx, ebx                ;         cbits += i;
131         add     edi, ebx                ;         uval += i;
132         add     ecx, byte 1             ;         cbits++; /* skip over stop bit */
133         test    ecx, ~31
134         jz      near .break1            ;         if(cbits >= FLAC__BITS_PER_WORD) { /* faster way of testing if(cbits == FLAC__BITS_PER_WORD) */
135                                         ;           crc16_update_word_(br, br->buffer[cwords]);
136         push    edi                     ;               [need more registers]
137         bswap   edx                     ;               edx = br->buffer[cwords] swapped; now we can CRC the bytes from LSByte to MSByte which makes things much easier
138         mov     ecx, [ebp + 28]         ;               ecx <- br->crc16_align
139         mov     eax, [ebp + 24]         ;               ax <- br->read_crc (a.k.a. crc)
140 %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE
141         mov     edi, _FLAC__crc16_table
142 %else
143         mov     edi, FLAC__crc16_table
144 %endif
145         ;; eax (ax)     crc a.k.a. br->read_crc
146         ;; ebx (bl)     intermediate result index into FLAC__crc16_table[]
147         ;; ecx          br->crc16_align
148         ;; edx          byteswapped brword to CRC
149         ;; esi          cwords
150         ;; edi          unsigned FLAC__crc16_table[]
151         ;; ebp          br
152         test    ecx, ecx                ;               switch(br->crc16_align) ...
153         jnz     .c0b4                   ;               [br->crc16_align is 0 the vast majority of the time so we optimize the common case]
154 .c0b0:  xor     dl, ah                  ;               dl <- (crc>>8)^(word>>24)
155         movzx   ebx, dl
156         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word>>24)]
157         shl     eax, 8                  ;               ax <- (crc<<8)
158         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word>>24)]
159 .c0b1:  xor     dh, ah                  ;               dh <- (crc>>8)^((word>>16)&0xff))
160         movzx   ebx, dh
161         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
162         shl     eax, 8                  ;               ax <- (crc<<8)
163         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
164         shr     edx, 16
165 .c0b2:  xor     dl, ah                  ;               dl <- (crc>>8)^((word>>8)&0xff))
166         movzx   ebx, dl
167         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
168         shl     eax, 8                  ;               ax <- (crc<<8)
169         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
170 .c0b3:  xor     dh, ah                  ;               dh <- (crc>>8)^(word&0xff)
171         movzx   ebx, dh
172         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word&0xff)]
173         shl     eax, 8                  ;               ax <- (crc<<8)
174         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word&0xff)]
175         movzx   eax, ax
176         mov     [ebp + 24], eax         ;               br->read_crc <- crc
177         pop     edi
178
179         add     esi, byte 1             ;           cwords++;
180         xor     ecx, ecx                ;           cbits = 0;
181                                         ;         }
182         jmp     near .break1            ;         goto break1;
183         ;; this section relocated out of the way for performance
184 .c0b4:
185         mov     [ebp + 28], dword 0     ;               br->crc16_align <- 0
186         cmp     ecx, 8
187         je      .c0b1
188         shr     edx, 16
189         cmp     ecx, 16
190         je      .c0b2
191         jmp     .c0b3
192
193         ;; this section relocated out of the way for performance
194 .c1b4:
195         mov     [ebp + 28], dword 0     ;               br->crc16_align <- 0
196         cmp     ecx, 8
197         je      .c1b1
198         shr     edx, 16
199         cmp     ecx, 16
200         je      .c1b2
201         jmp     .c1b3
202
203 .c1_next2:                              ;       } else {
204         ;; ecx          cbits
205         ;; edx          current brword 'b'
206         ;; esi          cwords
207         ;; edi          uval
208         ;; ebp          br
209         add     edi, 32
210         sub     edi, ecx                ;         uval += FLAC__BITS_PER_WORD - cbits;
211                                         ;         crc16_update_word_(br, br->buffer[cwords]);
212         push    edi                     ;               [need more registers]
213         bswap   edx                     ;               edx = br->buffer[cwords] swapped; now we can CRC the bytes from LSByte to MSByte which makes things much easier
214         mov     ecx, [ebp + 28]         ;               ecx <- br->crc16_align
215         mov     eax, [ebp + 24]         ;               ax <- br->read_crc (a.k.a. crc)
216 %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE
217         mov     edi, _FLAC__crc16_table
218 %else
219         mov     edi, FLAC__crc16_table
220 %endif
221         ;; eax (ax)     crc a.k.a. br->read_crc
222         ;; ebx (bl)     intermediate result index into FLAC__crc16_table[]
223         ;; ecx          br->crc16_align
224         ;; edx          byteswapped brword to CRC
225         ;; esi          cwords
226         ;; edi          unsigned FLAC__crc16_table[]
227         ;; ebp          br
228         test    ecx, ecx                ;               switch(br->crc16_align) ...
229         jnz     .c1b4                   ;               [br->crc16_align is 0 the vast majority of the time so we optimize the common case]
230 .c1b0:  xor     dl, ah                  ;               dl <- (crc>>8)^(word>>24)
231         movzx   ebx, dl
232         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word>>24)]
233         shl     eax, 8                  ;               ax <- (crc<<8)
234         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word>>24)]
235 .c1b1:  xor     dh, ah                  ;               dh <- (crc>>8)^((word>>16)&0xff))
236         movzx   ebx, dh
237         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
238         shl     eax, 8                  ;               ax <- (crc<<8)
239         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
240         shr     edx, 16
241 .c1b2:  xor     dl, ah                  ;               dl <- (crc>>8)^((word>>8)&0xff))
242         movzx   ebx, dl
243         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
244         shl     eax, 8                  ;               ax <- (crc<<8)
245         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
246 .c1b3:  xor     dh, ah                  ;               dh <- (crc>>8)^(word&0xff)
247         movzx   ebx, dh
248         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word&0xff)]
249         shl     eax, 8                  ;               ax <- (crc<<8)
250         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word&0xff)]
251         movzx   eax, ax
252         mov     [ebp + 24], eax         ;               br->read_crc <- crc
253         pop     edi
254
255         add     esi, byte 1             ;         cwords++;
256         xor     ecx, ecx                ;         cbits = 0;
257                                         ;         /* didn't find stop bit yet, have to keep going... */
258                                         ;       }
259
260         cmp     esi, [ebp + 8]          ;     } while(cwords < br->words)   /* if we've not consumed up to a partial tail word... */
261         jb      near .c1_loop
262
263 .c1_next1:
264         ; at this point we've eaten up all the whole words; have to try
265         ; reading through any tail bytes before calling the read callback.
266         ; this is a repeat of the above logic adjusted for the fact we
267         ; don't have a whole word.  note though if the client is feeding
268         ; us data a byte at a time (unlikely), br->consumed_bits may not
269         ; be zero.
270         ;; ecx          cbits
271         ;; esi          cwords
272         ;; edi          uval
273         ;; ebp          br
274         mov     edx, [ebp + 12]         ;     edx <- br->bytes
275         shl     edx, 3                  ;     edx <- br->bytes*8
276         cmp     edx, ecx
277         jbe     .read1                  ;     if(br->bytes*8 > cbits) {  [NOTE: this case is rare so it doesn't have to be all that fast ]
278         mov     ebx, [ebp]
279                                         ;       edx <- const unsigned end = br->bytes * 8;
280         mov     eax, [ebx + 4*esi]      ;       b = br->buffer[cwords]
281         xchg    edx, ecx                ;       [edx <- cbits , ecx <- end]
282         mov     ebx, 0xffffffff         ;       ebx <- FLAC__WORD_ALL_ONES
283         shr     ebx, cl                 ;       ebx <- FLAC__WORD_ALL_ONES >> end
284         not     ebx                     ;       ebx <- ~(FLAC__WORD_ALL_ONES >> end)
285         xchg    edx, ecx                ;       [edx <- end , ecx <- cbits]
286         and     eax, ebx                ;       b = (br->buffer[cwords] & ~(FLAC__WORD_ALL_ONES >> end));
287         shl     eax, cl                 ;       b = (br->buffer[cwords] & ~(FLAC__WORD_ALL_ONES >> end)) << cbits;
288         test    eax, eax                ;         (still have to test since cbits may be 0, thus ZF not updated for shl eax,0)
289         jz      .c1_next3               ;       if(b) {
290         bsr     ebx, eax
291         not     ebx
292         and     ebx, 31                 ;         ebx = 'i' = # of leading 0 bits in 'b' (eax)
293         add     ecx, ebx                ;         cbits += i;
294         add     edi, ebx                ;         uval += i;
295         add     ecx, byte 1             ;         cbits++; /* skip over stop bit */
296         jmp     short .break1           ;         goto break1;
297 .c1_next3:                              ;       } else {
298         sub     edi, ecx
299         add     edi, edx                ;         uval += end - cbits;
300         mov     ecx, edx                ;         cbits = end
301                                         ;         /* didn't find stop bit yet, have to keep going... */
302                                         ;       }
303                                         ;     }
304 .read1:
305         ; flush registers and read; bitreader_read_from_client_() does
306         ; not touch br->consumed_bits at all but we still need to set
307         ; it in case it fails and we have to return false.
308         ;; ecx          cbits
309         ;; esi          cwords
310         ;; edi          uval
311         ;; ebp          br
312         mov     [ebp + 16], esi         ;     br->consumed_words = cwords;
313         mov     [ebp + 20], ecx         ;     br->consumed_bits = cbits;
314         push    ecx                     ;     /* save */
315         push    ebp                     ;     /* push br argument */
316 %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE
317         call    _bitreader_read_from_client_
318 %else
319         call    bitreader_read_from_client_
320 %endif
321         pop     edx                     ;     /* discard, unused */
322         pop     ecx                     ;     /* restore */
323         mov     esi, [ebp + 16]         ;     cwords = br->consumed_words;
324                                         ;     ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits;
325         mov     ebx, [ebp + 8]          ;       ebx <- br->words
326         sub     ebx, esi                ;       ebx <- br->words-cwords
327         shl     ebx, 2                  ;       ebx <- (br->words-cwords)*FLAC__BYTES_PER_WORD
328         add     ebx, [ebp + 12]         ;       ebx <- (br->words-cwords)*FLAC__BYTES_PER_WORD + br->bytes
329         shl     ebx, 3                  ;       ebx <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8
330         sub     ebx, ecx                ;       ebx <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits
331         add     ebx, edi                ;       ebx <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits + uval
332                                         ;           + uval to offset our count by the # of unary bits already
333                                         ;           consumed before the read, because we will add these back
334                                         ;           in all at once at break1
335         mov     [esp], ebx              ;       ucbits <- ebx
336         test    eax, eax                ;     if(!bitreader_read_from_client_(br))
337         jnz     near .unary_loop
338         jmp     .end                    ;       return false; /* eax (the return value) is already 0 */
339                                         ;   } /* end while(1) unary part */
340
341         ALIGN 16
342 .break1:
343         ;; ecx          cbits
344         ;; esi          cwords
345         ;; edi          uval
346         ;; ebp          br
347         ;; [esp]        ucbits
348         sub     [esp], edi              ;   ucbits -= uval;
349         sub     dword [esp], byte 1     ;   ucbits--; /* account for stop bit */
350
351         ;
352         ; read binary part
353         ;
354         mov     ebx, [esp + 36]         ;   ebx <- parameter
355         test    ebx, ebx                ;   if(parameter) {
356         jz      near .break2
357 .read2:
358         cmp     [esp], ebx              ;     while(ucbits < parameter) {
359         jae     .c2_next1
360         ; flush registers and read; bitreader_read_from_client_() does
361         ; not touch br->consumed_bits at all but we still need to set
362         ; it in case it fails and we have to return false.
363         mov     [ebp + 16], esi         ;       br->consumed_words = cwords;
364         mov     [ebp + 20], ecx         ;       br->consumed_bits = cbits;
365         push    ecx                     ;       /* save */
366         push    ebp                     ;       /* push br argument */
367 %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE
368         call    _bitreader_read_from_client_
369 %else
370         call    bitreader_read_from_client_
371 %endif
372         pop     edx                     ;       /* discard, unused */
373         pop     ecx                     ;       /* restore */
374         mov     esi, [ebp + 16]         ;       cwords = br->consumed_words;
375                                         ;       ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits;
376         mov     edx, [ebp + 8]          ;         edx <- br->words
377         sub     edx, esi                ;         edx <- br->words-cwords
378         shl     edx, 2                  ;         edx <- (br->words-cwords)*FLAC__BYTES_PER_WORD
379         add     edx, [ebp + 12]         ;         edx <- (br->words-cwords)*FLAC__BYTES_PER_WORD + br->bytes
380         shl     edx, 3                  ;         edx <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8
381         sub     edx, ecx                ;         edx <- (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits
382         mov     [esp], edx              ;         ucbits <- edx
383         test    eax, eax                ;       if(!bitreader_read_from_client_(br))
384         jnz     .read2
385         jmp     .end                    ;         return false; /* eax (the return value) is already 0 */
386                                         ;     }
387 .c2_next1:
388         ;; ebx          parameter
389         ;; ecx          cbits
390         ;; esi          cwords
391         ;; edi          uval
392         ;; ebp          br
393         ;; [esp]        ucbits
394         cmp     esi, [ebp + 8]          ;     if(cwords < br->words) { /* if we've not consumed up to a partial tail word... */
395         jae     near .c2_next2
396         test    ecx, ecx                ;       if(cbits) {
397         jz      near .c2_next3          ;         /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */
398         mov     eax, 32
399         mov     edx, [ebp]
400         sub     eax, ecx                ;         const unsigned n = FLAC__BITS_PER_WORD - cbits;
401         mov     edx, [edx + 4*esi]      ;         const brword word = br->buffer[cwords];
402         cmp     ebx, eax                ;         if(parameter < n) {
403         jae     .c2_next4
404                                         ;           uval <<= parameter;
405                                         ;           uval |= (word & (FLAC__WORD_ALL_ONES >> cbits)) >> (n-parameter);
406         shl     edx, cl
407         xchg    ebx, ecx
408         shld    edi, edx, cl
409         add     ebx, ecx                ;           cbits += parameter;
410         xchg    ebx, ecx                ;           ebx <- parameter, ecx <- cbits
411         jmp     .break2                 ;           goto break2;
412                                         ;         }
413 .c2_next4:
414                                         ;         uval <<= n;
415                                         ;         uval |= word & (FLAC__WORD_ALL_ONES >> cbits);
416 %if 1
417         rol     edx, cl                 ;            @@@@@@OPT: may be faster to use rol to save edx so we can restore it for CRC'ing
418                                         ;            @@@@@@OPT: or put parameter in ch instead and free up ebx completely again
419 %else
420         shl     edx, cl
421 %endif
422         xchg    eax, ecx
423         shld    edi, edx, cl
424         xchg    eax, ecx
425 %if 1
426         ror     edx, cl                 ;            restored.
427 %else
428         mov     edx, [ebp]
429         mov     edx, [edx + 4*esi]
430 %endif
431                                         ;         crc16_update_word_(br, br->buffer[cwords]);
432         push    edi                     ;               [need more registers]
433         push    ebx                     ;               [need more registers]
434         push    eax                     ;               [need more registers]
435         bswap   edx                     ;               edx = br->buffer[cwords] swapped; now we can CRC the bytes from LSByte to MSByte which makes things much easier
436         mov     ecx, [ebp + 28]         ;               ecx <- br->crc16_align
437         mov     eax, [ebp + 24]         ;               ax <- br->read_crc (a.k.a. crc)
438 %ifdef FLAC__PUBLIC_NEEDS_UNDERSCORE
439         mov     edi, _FLAC__crc16_table
440 %else
441         mov     edi, FLAC__crc16_table
442 %endif
443         ;; eax (ax)     crc a.k.a. br->read_crc
444         ;; ebx (bl)     intermediate result index into FLAC__crc16_table[]
445         ;; ecx          br->crc16_align
446         ;; edx          byteswapped brword to CRC
447         ;; esi          cwords
448         ;; edi          unsigned FLAC__crc16_table[]
449         ;; ebp          br
450         test    ecx, ecx                ;               switch(br->crc16_align) ...
451         jnz     .c2b4                   ;               [br->crc16_align is 0 the vast majority of the time so we optimize the common case]
452 .c2b0:  xor     dl, ah                  ;               dl <- (crc>>8)^(word>>24)
453         movzx   ebx, dl
454         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word>>24)]
455         shl     eax, 8                  ;               ax <- (crc<<8)
456         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word>>24)]
457 .c2b1:  xor     dh, ah                  ;               dh <- (crc>>8)^((word>>16)&0xff))
458         movzx   ebx, dh
459         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
460         shl     eax, 8                  ;               ax <- (crc<<8)
461         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>16)&0xff))]
462         shr     edx, 16
463 .c2b2:  xor     dl, ah                  ;               dl <- (crc>>8)^((word>>8)&0xff))
464         movzx   ebx, dl
465         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
466         shl     eax, 8                  ;               ax <- (crc<<8)
467         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^((word>>8)&0xff))]
468 .c2b3:  xor     dh, ah                  ;               dh <- (crc>>8)^(word&0xff)
469         movzx   ebx, dh
470         mov     ecx, [ebx*4 + edi]      ;               cx <- FLAC__crc16_table[(crc>>8)^(word&0xff)]
471         shl     eax, 8                  ;               ax <- (crc<<8)
472         xor     eax, ecx                ;               crc <- ax <- (crc<<8) ^ FLAC__crc16_table[(crc>>8)^(word&0xff)]
473         movzx   eax, ax
474         mov     [ebp + 24], eax         ;               br->read_crc <- crc
475         pop     eax
476         pop     ebx
477         pop     edi
478         add     esi, byte 1             ;         cwords++;
479         mov     ecx, ebx
480         sub     ecx, eax                ;         cbits = parameter - n;
481         jz      .break2                 ;         if(cbits) { /* parameter > n, i.e. if there are still bits left to read, there have to be less than 32 so they will all be in the next word */
482                                         ;           uval <<= cbits;
483                                         ;           uval |= (br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits));
484         mov     eax, [ebp]
485         mov     eax, [eax + 4*esi]
486         shld    edi, eax, cl
487                                         ;         }
488         jmp     .break2                 ;         goto break2;
489
490         ;; this section relocated out of the way for performance
491 .c2b4:
492         mov     [ebp + 28], dword 0     ;               br->crc16_align <- 0
493         cmp     ecx, 8
494         je      .c2b1
495         shr     edx, 16
496         cmp     ecx, 16
497         je      .c2b2
498         jmp     .c2b3
499
500 .c2_next3:                              ;       } else {
501         mov     ecx, ebx                ;         cbits = parameter;
502                                         ;         uval <<= cbits;
503                                         ;         uval |= (br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits));
504         mov     eax, [ebp]
505         mov     eax, [eax + 4*esi]
506         shld    edi, eax, cl
507         jmp     .break2                 ;         goto break2;
508                                         ;       }
509 .c2_next2:                              ;     } else {
510         ; in this case we're starting our read at a partial tail word;
511         ; the reader has guaranteed that we have at least 'parameter'
512         ; bits available to read, which makes this case simpler.
513                                         ;       uval <<= parameter;
514                                         ;       if(cbits) {
515                                         ;         /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */
516                                         ;         uval |= (br->buffer[cwords] & (FLAC__WORD_ALL_ONES >> cbits)) >> (FLAC__BITS_PER_WORD-cbits-parameter);
517                                         ;         cbits += parameter;
518                                         ;         goto break2;
519                                         ;       } else {
520                                         ;         cbits = parameter;
521                                         ;         uval |= br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits);
522                                         ;         goto break2;
523                                         ;       }
524                                         ;       the above is much shorter in assembly:
525         mov     eax, [ebp]
526         mov     eax, [eax + 4*esi]      ;       eax <- br->buffer[cwords]
527         shl     eax, cl                 ;       eax <- br->buffer[cwords] << cbits
528         add     ecx, ebx                ;       cbits += parameter
529         xchg    ebx, ecx                ;       ebx <- cbits, ecx <- parameter
530         shld    edi, eax, cl            ;       uval <<= parameter <<< 'parameter' bits of tail word
531         xchg    ebx, ecx                ;       ebx <- parameter, ecx <- cbits
532                                         ;     }
533                                         ;   }
534 .break2:
535         sub     [esp], ebx              ;   ucbits -= parameter;
536
537         ;
538         ; compose the value
539         ;
540         mov     ebx, [esp + 28]         ;   ebx <- vals
541         mov     edx, edi                ;   edx <- uval
542         and     edi, 1                  ;   edi <- uval & 1
543         shr     edx, 1                  ;   edx <- uval >> 1
544         neg     edi                     ;   edi <- -(int)(uval & 1)
545         xor     edx, edi                ;   edx <- (uval >> 1 ^ -(int)(uval & 1))
546         mov     [ebx], edx              ;   *vals <- edx
547         sub     dword [esp + 32], byte 1        ;   --nvals;
548         jz      .finished               ;   if(nvals == 0) /* jump to finish */
549         xor     edi, edi                ;   uval = 0;
550         add     dword [esp + 28], 4     ;   ++vals
551         jmp     .val_loop               ; }
552
553 .finished:
554         mov     [ebp + 16], esi         ; br->consumed_words = cwords;
555         mov     [ebp + 20], ecx         ; br->consumed_bits = cbits;
556         mov     eax, 1
557 .end:
558         add     esp, 4
559         pop     edi
560         pop     esi
561         pop     ebx
562         pop     ebp
563         ret
564
565 end
566
567 %ifdef OBJ_FORMAT_elf
568         section .note.GNU-stack noalloc
569 %endif