]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/check/crc64_x86.s
Imported to git.
[icculus/xz.git] / src / liblzma / check / crc64_x86.s
1 /*
2  * Speed-optimized CRC64 using slicing-by-four algorithm
3  * Instruction set: i386
4  * Optimized for:   i686
5  *
6  * This code has been put into the public domain by its authors:
7  * Igor Pavlov <http://7-zip.org/>
8  * Lasse Collin <lasse.collin@tukaani.org>
9  *
10  * This code needs lzma_crc64_table, which can be created using the
11  * following C code:
12
13 uint64_t lzma_crc64_table[4][256];
14
15 void
16 init_table(void)
17 {
18         static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
19
20         for (size_t s = 0; s < 4; ++s) {
21                 for (size_t b = 0; b < 256; ++b) {
22                         uint64_t r = s == 0 ? b : lzma_crc64_table[s - 1][b];
23
24                         for (size_t i = 0; i < 8; ++i) {
25                                 if (r & 1)
26                                         r = (r >> 1) ^ poly64;
27                                 else
28                                         r >>= 1;
29                         }
30
31                         lzma_crc64_table[s][b] = r;
32                 }
33         }
34 }
35
36  * The prototype of the CRC64 function:
37  * extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
38  */
39
40         .text
41         .global lzma_crc64
42         .type   lzma_crc64, @function
43
44         .align  16
45 lzma_crc64:
46         /*
47          * Register usage:
48          * %eax crc LSB
49          * %edx crc MSB
50          * %esi buf
51          * %edi size or buf + size
52          * %ebx lzma_crc64_table
53          * %ebp Table index
54          * %ecx Temporary
55          */
56         pushl   %ebx
57         pushl   %esi
58         pushl   %edi
59         pushl   %ebp
60         movl    0x14(%esp), %esi /* buf */
61         movl    0x18(%esp), %edi /* size */
62         movl    0x1C(%esp), %eax /* crc LSB */
63         movl    0x20(%esp), %edx /* crc MSB */
64
65         /*
66          * Store the address of lzma_crc64_table to %ebx. This is needed to
67          * get position-independent code (PIC).
68          */
69         call    .L_PIC
70 .L_PIC:
71         popl    %ebx
72         addl    $_GLOBAL_OFFSET_TABLE_+[.-.L_PIC], %ebx
73         movl    lzma_crc64_table@GOT(%ebx), %ebx
74
75         /* Complement the initial value. */
76         notl    %eax
77         notl    %edx
78
79 .L_align:
80         /*
81          * Check if there is enough input to use slicing-by-four.
82          * We need eight bytes, because the loop pre-reads four bytes.
83          */
84         cmpl    $8, %edi
85         jl      .L_rest
86
87         /* Check if we have reached alignment of four bytes. */
88         testl   $3, %esi
89         jz      .L_slice
90
91         /* Calculate CRC of the next input byte. */
92         movzbl  (%esi), %ebp
93         incl    %esi
94         movzbl  %al, %ecx
95         xorl    %ecx, %ebp
96         shrdl   $8, %edx, %eax
97         xorl    (%ebx, %ebp, 8), %eax
98         shrl    $8, %edx
99         xorl    4(%ebx, %ebp, 8), %edx
100         decl    %edi
101         jmp     .L_align
102
103 .L_slice:
104         /*
105          * If we get here, there's at least eight bytes of aligned input
106          * available. Make %edi multiple of four bytes. Store the possible
107          * remainder over the "size" variable in the argument stack.
108          */
109         movl    %edi, 0x18(%esp)
110         andl    $-4, %edi
111         subl    %edi, 0x18(%esp)
112
113         /*
114          * Let %edi be buf + size - 4 while running the main loop. This way
115          * we can compare for equality to determine when exit the loop.
116          */
117         addl    %esi, %edi
118         subl    $4, %edi
119
120         /* Read in the first four aligned bytes. */
121         movl    (%esi), %ecx
122
123 .L_loop:
124         xorl    %eax, %ecx
125         movzbl  %cl, %ebp
126         movl    0x1800(%ebx, %ebp, 8), %eax
127         xorl    %edx, %eax
128         movl    0x1804(%ebx, %ebp, 8), %edx
129         movzbl  %ch, %ebp
130         xorl    0x1000(%ebx, %ebp, 8), %eax
131         xorl    0x1004(%ebx, %ebp, 8), %edx
132         shrl    $16, %ecx
133         movzbl  %cl, %ebp
134         xorl    0x0800(%ebx, %ebp, 8), %eax
135         xorl    0x0804(%ebx, %ebp, 8), %edx
136         movzbl  %ch, %ebp
137         addl    $4, %esi
138         xorl    (%ebx, %ebp, 8), %eax
139         xorl    4(%ebx, %ebp, 8), %edx
140
141         /* Check for end of aligned input. */
142         cmpl    %edi, %esi
143
144         /*
145          * Copy the next input byte to %ecx. It is slightly faster to
146          * read it here than at the top of the loop.
147          */
148         movl    (%esi), %ecx
149         jl      .L_loop
150
151         /*
152          * Process the remaining four bytes, which we have already
153          * copied to %ecx.
154          */
155         xorl    %eax, %ecx
156         movzbl  %cl, %ebp
157         movl    0x1800(%ebx, %ebp, 8), %eax
158         xorl    %edx, %eax
159         movl    0x1804(%ebx, %ebp, 8), %edx
160         movzbl  %ch, %ebp
161         xorl    0x1000(%ebx, %ebp, 8), %eax
162         xorl    0x1004(%ebx, %ebp, 8), %edx
163         shrl    $16, %ecx
164         movzbl  %cl, %ebp
165         xorl    0x0800(%ebx, %ebp, 8), %eax
166         xorl    0x0804(%ebx, %ebp, 8), %edx
167         movzbl  %ch, %ebp
168         addl    $4, %esi
169         xorl    (%ebx, %ebp, 8), %eax
170         xorl    4(%ebx, %ebp, 8), %edx
171
172         /* Copy the number of remaining bytes to %edi. */
173         movl    0x18(%esp), %edi
174
175 .L_rest:
176         /* Check for end of input. */
177         testl   %edi, %edi
178         jz      .L_return
179
180         /* Calculate CRC of the next input byte. */
181         movzbl  (%esi), %ebp
182         incl    %esi
183         movzbl  %al, %ecx
184         xorl    %ecx, %ebp
185         shrdl   $8, %edx, %eax
186         xorl    (%ebx, %ebp, 8), %eax
187         shrl    $8, %edx
188         xorl    4(%ebx, %ebp, 8), %edx
189         decl    %edi
190         jmp     .L_rest
191
192 .L_return:
193         /* Complement the final value. */
194         notl    %eax
195         notl    %edx
196
197         popl    %ebp
198         popl    %edi
199         popl    %esi
200         popl    %ebx
201         ret
202
203         .size   lzma_crc32, .-lzma_crc32