dodan override za lintian
[ossec-hids.git] / src / external / zlib-1.2.11 / contrib / masmx64 / inffasx64.asm
1 ; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding\r
2 ; version for AMD64 on Windows using Microsoft C compiler\r
3 ;\r
4 ; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c\r
5 ; inffasx64.asm is called by inffas8664.c, which contain more info.\r
6 \r
7 \r
8 ; to compile this file, I use option\r
9 ;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm\r
10 ;   with Microsoft Macro Assembler (x64) for AMD64\r
11 ;\r
12 \r
13 ; This file compile with Microsoft Macro Assembler (x64) for AMD64\r
14 ;\r
15 ;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK\r
16 ;\r
17 ;   (you can get Windows WDK with ml64 for AMD64 from\r
18 ;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)\r
19 ;\r
20 \r
21 \r
22 .code\r
23 inffas8664fnc PROC\r
24 \r
25 ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and\r
26 ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp\r
27 ;\r
28 ; All registers must be preserved across the call, except for\r
29 ;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.\r
30 \r
31 \r
32         mov [rsp-8],rsi\r
33         mov [rsp-16],rdi\r
34         mov [rsp-24],r12\r
35         mov [rsp-32],r13\r
36         mov [rsp-40],r14\r
37         mov [rsp-48],r15\r
38         mov [rsp-56],rbx\r
39 \r
40         mov rax,rcx\r
41 \r
42         mov     [rax+8], rbp       ; /* save regs rbp and rsp */\r
43         mov     [rax], rsp\r
44 \r
45         mov     rsp, rax          ; /* make rsp point to &ar */\r
46 \r
47         mov     rsi, [rsp+16]      ; /* rsi  = in */\r
48         mov     rdi, [rsp+32]      ; /* rdi  = out */\r
49         mov     r9, [rsp+24]       ; /* r9   = last */\r
50         mov     r10, [rsp+48]      ; /* r10  = end */\r
51         mov     rbp, [rsp+64]      ; /* rbp  = lcode */\r
52         mov     r11, [rsp+72]      ; /* r11  = dcode */\r
53         mov     rdx, [rsp+80]      ; /* rdx  = hold */\r
54         mov     ebx, [rsp+88]      ; /* ebx  = bits */\r
55         mov     r12d, [rsp+100]    ; /* r12d = lmask */\r
56         mov     r13d, [rsp+104]    ; /* r13d = dmask */\r
57                                           ; /* r14d = len */\r
58                                           ; /* r15d = dist */\r
59 \r
60 \r
61         cld\r
62         cmp     r10, rdi\r
63         je      L_one_time           ; /* if only one decode left */\r
64         cmp     r9, rsi\r
65 \r
66     jne L_do_loop\r
67 \r
68 \r
69 L_one_time:\r
70         mov     r8, r12           ; /* r8 = lmask */\r
71         cmp     bl, 32\r
72         ja      L_get_length_code_one_time\r
73 \r
74         lodsd                         ; /* eax = *(uint *)in++ */\r
75         mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
76         add     bl, 32             ; /* bits += 32 */\r
77         shl     rax, cl\r
78         or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
79         jmp     L_get_length_code_one_time\r
80 \r
81 ALIGN 4\r
82 L_while_test:\r
83         cmp     r10, rdi\r
84         jbe     L_break_loop\r
85         cmp     r9, rsi\r
86         jbe     L_break_loop\r
87 \r
88 L_do_loop:\r
89         mov     r8, r12           ; /* r8 = lmask */\r
90         cmp     bl, 32\r
91         ja      L_get_length_code    ; /* if (32 < bits) */\r
92 \r
93         lodsd                         ; /* eax = *(uint *)in++ */\r
94         mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
95         add     bl, 32             ; /* bits += 32 */\r
96         shl     rax, cl\r
97         or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
98 \r
99 L_get_length_code:\r
100         and     r8, rdx            ; /* r8 &= hold */\r
101         mov     eax, [rbp+r8*4]  ; /* eax = lcode[hold & lmask] */\r
102 \r
103         mov     cl, ah            ; /* cl = this.bits */\r
104         sub     bl, ah            ; /* bits -= this.bits */\r
105         shr     rdx, cl           ; /* hold >>= this.bits */\r
106 \r
107         test    al, al\r
108         jnz     L_test_for_length_base ; /* if (op != 0) 45.7% */\r
109 \r
110         mov     r8, r12            ; /* r8 = lmask */\r
111         shr     eax, 16            ; /* output this.val char */\r
112         stosb\r
113 \r
114 L_get_length_code_one_time:\r
115         and     r8, rdx            ; /* r8 &= hold */\r
116         mov     eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */\r
117 \r
118 L_dolen:\r
119         mov     cl, ah            ; /* cl = this.bits */\r
120         sub     bl, ah            ; /* bits -= this.bits */\r
121         shr     rdx, cl           ; /* hold >>= this.bits */\r
122 \r
123         test    al, al\r
124         jnz     L_test_for_length_base ; /* if (op != 0) 45.7% */\r
125 \r
126         shr     eax, 16            ; /* output this.val char */\r
127         stosb\r
128         jmp     L_while_test\r
129 \r
130 ALIGN 4\r
131 L_test_for_length_base:\r
132         mov     r14d, eax         ; /* len = this */\r
133         shr     r14d, 16           ; /* len = this.val */\r
134         mov     cl, al\r
135 \r
136         test    al, 16\r
137         jz      L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */\r
138         and     cl, 15             ; /* op &= 15 */\r
139         jz      L_decode_distance    ; /* if (!op) */\r
140 \r
141 L_add_bits_to_len:\r
142         sub     bl, cl\r
143         xor     eax, eax\r
144         inc     eax\r
145         shl     eax, cl\r
146         dec     eax\r
147         and     eax, edx          ; /* eax &= hold */\r
148         shr     rdx, cl\r
149         add     r14d, eax         ; /* len += hold & mask[op] */\r
150 \r
151 L_decode_distance:\r
152         mov     r8, r13           ; /* r8 = dmask */\r
153         cmp     bl, 32\r
154         ja      L_get_distance_code  ; /* if (32 < bits) */\r
155 \r
156         lodsd                         ; /* eax = *(uint *)in++ */\r
157         mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
158         add     bl, 32             ; /* bits += 32 */\r
159         shl     rax, cl\r
160         or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
161 \r
162 L_get_distance_code:\r
163         and     r8, rdx           ; /* r8 &= hold */\r
164         mov     eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */\r
165 \r
166 L_dodist:\r
167         mov     r15d, eax         ; /* dist = this */\r
168         shr     r15d, 16           ; /* dist = this.val */\r
169         mov     cl, ah\r
170         sub     bl, ah            ; /* bits -= this.bits */\r
171         shr     rdx, cl           ; /* hold >>= this.bits */\r
172         mov     cl, al            ; /* cl = this.op */\r
173 \r
174         test    al, 16             ; /* if ((op & 16) == 0) */\r
175         jz      L_test_for_second_level_dist\r
176         and     cl, 15             ; /* op &= 15 */\r
177         jz      L_check_dist_one\r
178 \r
179 L_add_bits_to_dist:\r
180         sub     bl, cl\r
181         xor     eax, eax\r
182         inc     eax\r
183         shl     eax, cl\r
184         dec     eax                 ; /* (1 << op) - 1 */\r
185         and     eax, edx          ; /* eax &= hold */\r
186         shr     rdx, cl\r
187         add     r15d, eax         ; /* dist += hold & ((1 << op) - 1) */\r
188 \r
189 L_check_window:\r
190         mov     r8, rsi           ; /* save in so from can use it's reg */\r
191         mov     rax, rdi\r
192         sub     rax, [rsp+40]      ; /* nbytes = out - beg */\r
193 \r
194         cmp     eax, r15d\r
195         jb      L_clip_window        ; /* if (dist > nbytes) 4.2% */\r
196 \r
197         mov     ecx, r14d         ; /* ecx = len */\r
198         mov     rsi, rdi\r
199         sub     rsi, r15          ; /* from = out - dist */\r
200 \r
201         sar     ecx, 1\r
202         jnc     L_copy_two           ; /* if len % 2 == 0 */\r
203 \r
204         rep     movsw\r
205         mov     al, [rsi]\r
206         mov     [rdi], al\r
207         inc     rdi\r
208 \r
209         mov     rsi, r8           ; /* move in back to %rsi, toss from */\r
210         jmp     L_while_test\r
211 \r
212 L_copy_two:\r
213         rep     movsw\r
214         mov     rsi, r8           ; /* move in back to %rsi, toss from */\r
215         jmp     L_while_test\r
216 \r
217 ALIGN 4\r
218 L_check_dist_one:\r
219         cmp     r15d, 1            ; /* if dist 1, is a memset */\r
220         jne     L_check_window\r
221         cmp     [rsp+40], rdi      ; /* if out == beg, outside window */\r
222         je      L_check_window\r
223 \r
224         mov     ecx, r14d         ; /* ecx = len */\r
225         mov     al, [rdi-1]\r
226         mov     ah, al\r
227 \r
228         sar     ecx, 1\r
229         jnc     L_set_two\r
230         mov     [rdi], al\r
231         inc     rdi\r
232 \r
233 L_set_two:\r
234         rep     stosw\r
235         jmp     L_while_test\r
236 \r
237 ALIGN 4\r
238 L_test_for_second_level_length:\r
239         test    al, 64\r
240         jnz     L_test_for_end_of_block ; /* if ((op & 64) != 0) */\r
241 \r
242         xor     eax, eax\r
243         inc     eax\r
244         shl     eax, cl\r
245         dec     eax\r
246         and     eax, edx         ; /* eax &= hold */\r
247         add     eax, r14d        ; /* eax += len */\r
248         mov     eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/\r
249         jmp     L_dolen\r
250 \r
251 ALIGN 4\r
252 L_test_for_second_level_dist:\r
253         test    al, 64\r
254         jnz     L_invalid_distance_code ; /* if ((op & 64) != 0) */\r
255 \r
256         xor     eax, eax\r
257         inc     eax\r
258         shl     eax, cl\r
259         dec     eax\r
260         and     eax, edx         ; /* eax &= hold */\r
261         add     eax, r15d        ; /* eax += dist */\r
262         mov     eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/\r
263         jmp     L_dodist\r
264 \r
265 ALIGN 4\r
266 L_clip_window:\r
267         mov     ecx, eax         ; /* ecx = nbytes */\r
268         mov     eax, [rsp+92]     ; /* eax = wsize, prepare for dist cmp */\r
269         neg     ecx                ; /* nbytes = -nbytes */\r
270 \r
271         cmp     eax, r15d\r
272         jb      L_invalid_distance_too_far ; /* if (dist > wsize) */\r
273 \r
274         add     ecx, r15d         ; /* nbytes = dist - nbytes */\r
275         cmp     dword ptr [rsp+96], 0\r
276         jne     L_wrap_around_window ; /* if (write != 0) */\r
277 \r
278         mov     rsi, [rsp+56]     ; /* from  = window */\r
279         sub     eax, ecx         ; /* eax  -= nbytes */\r
280         add     rsi, rax         ; /* from += wsize - nbytes */\r
281 \r
282         mov     eax, r14d        ; /* eax = len */\r
283         cmp     r14d, ecx\r
284         jbe     L_do_copy           ; /* if (nbytes >= len) */\r
285 \r
286         sub     eax, ecx         ; /* eax -= nbytes */\r
287         rep     movsb\r
288         mov     rsi, rdi\r
289         sub     rsi, r15         ; /* from = &out[ -dist ] */\r
290         jmp     L_do_copy\r
291 \r
292 ALIGN 4\r
293 L_wrap_around_window:\r
294         mov     eax, [rsp+96]     ; /* eax = write */\r
295         cmp     ecx, eax\r
296         jbe     L_contiguous_in_window ; /* if (write >= nbytes) */\r
297 \r
298         mov     esi, [rsp+92]     ; /* from  = wsize */\r
299         add     rsi, [rsp+56]     ; /* from += window */\r
300         add     rsi, rax         ; /* from += write */\r
301         sub     rsi, rcx         ; /* from -= nbytes */\r
302         sub     ecx, eax         ; /* nbytes -= write */\r
303 \r
304         mov     eax, r14d        ; /* eax = len */\r
305         cmp     eax, ecx\r
306         jbe     L_do_copy           ; /* if (nbytes >= len) */\r
307 \r
308         sub     eax, ecx         ; /* len -= nbytes */\r
309         rep     movsb\r
310         mov     rsi, [rsp+56]     ; /* from = window */\r
311         mov     ecx, [rsp+96]     ; /* nbytes = write */\r
312         cmp     eax, ecx\r
313         jbe     L_do_copy           ; /* if (nbytes >= len) */\r
314 \r
315         sub     eax, ecx         ; /* len -= nbytes */\r
316         rep     movsb\r
317         mov     rsi, rdi\r
318         sub     rsi, r15         ; /* from = out - dist */\r
319         jmp     L_do_copy\r
320 \r
321 ALIGN 4\r
322 L_contiguous_in_window:\r
323         mov     rsi, [rsp+56]     ; /* rsi = window */\r
324         add     rsi, rax\r
325         sub     rsi, rcx         ; /* from += write - nbytes */\r
326 \r
327         mov     eax, r14d        ; /* eax = len */\r
328         cmp     eax, ecx\r
329         jbe     L_do_copy           ; /* if (nbytes >= len) */\r
330 \r
331         sub     eax, ecx         ; /* len -= nbytes */\r
332         rep     movsb\r
333         mov     rsi, rdi\r
334         sub     rsi, r15         ; /* from = out - dist */\r
335         jmp     L_do_copy           ; /* if (nbytes >= len) */\r
336 \r
337 ALIGN 4\r
338 L_do_copy:\r
339         mov     ecx, eax         ; /* ecx = len */\r
340         rep     movsb\r
341 \r
342         mov     rsi, r8          ; /* move in back to %esi, toss from */\r
343         jmp     L_while_test\r
344 \r
345 L_test_for_end_of_block:\r
346         test    al, 32\r
347         jz      L_invalid_literal_length_code\r
348         mov     dword ptr [rsp+116], 1\r
349         jmp     L_break_loop_with_status\r
350 \r
351 L_invalid_literal_length_code:\r
352         mov     dword ptr [rsp+116], 2\r
353         jmp     L_break_loop_with_status\r
354 \r
355 L_invalid_distance_code:\r
356         mov     dword ptr [rsp+116], 3\r
357         jmp     L_break_loop_with_status\r
358 \r
359 L_invalid_distance_too_far:\r
360         mov     dword ptr [rsp+116], 4\r
361         jmp     L_break_loop_with_status\r
362 \r
363 L_break_loop:\r
364         mov     dword ptr [rsp+116], 0\r
365 \r
366 L_break_loop_with_status:\r
367 ; /* put in, out, bits, and hold back into ar and pop esp */\r
368         mov     [rsp+16], rsi     ; /* in */\r
369         mov     [rsp+32], rdi     ; /* out */\r
370         mov     [rsp+88], ebx     ; /* bits */\r
371         mov     [rsp+80], rdx     ; /* hold */\r
372 \r
373         mov     rax, [rsp]       ; /* restore rbp and rsp */\r
374         mov     rbp, [rsp+8]\r
375         mov     rsp, rax\r
376 \r
377 \r
378 \r
379         mov rsi,[rsp-8]\r
380         mov rdi,[rsp-16]\r
381         mov r12,[rsp-24]\r
382         mov r13,[rsp-32]\r
383         mov r14,[rsp-40]\r
384         mov r15,[rsp-48]\r
385         mov rbx,[rsp-56]\r
386 \r
387     ret 0\r
388 ;          :\r
389 ;          : "m" (ar)\r
390 ;          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",\r
391 ;            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"\r
392 ;    );\r
393 \r
394 inffas8664fnc   ENDP\r
395 ;_TEXT  ENDS\r
396 END\r