dodan override za lintian
[ossec-hids.git] / src / external / zlib-1.2.11 / contrib / masmx64 / gvmat64.asm
1 ;uInt longest_match_x64(\r
2 ;    deflate_state *s,\r
3 ;    IPos cur_match);                             /* current match */\r
4 \r
5 ; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64\r
6 ;  (AMD64 on Athlon 64, Opteron, Phenom\r
7 ;     and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7)\r
8 ; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant.\r
9 ;\r
10 ; File written by Gilles Vollant, by converting to assembly the longest_match\r
11 ;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.\r
12 ;\r
13 ;  and by taking inspiration on asm686 with masm, optimised assembly code\r
14 ;        from Brian Raiter, written 1998\r
15 ;\r
16 ;  This software is provided 'as-is', without any express or implied\r
17 ;  warranty.  In no event will the authors be held liable for any damages\r
18 ;  arising from the use of this software.\r
19 ;\r
20 ;  Permission is granted to anyone to use this software for any purpose,\r
21 ;  including commercial applications, and to alter it and redistribute it\r
22 ;  freely, subject to the following restrictions:\r
23 ;\r
24 ;  1. The origin of this software must not be misrepresented; you must not\r
25 ;     claim that you wrote the original software. If you use this software\r
26 ;     in a product, an acknowledgment in the product documentation would be\r
27 ;     appreciated but is not required.\r
28 ;  2. Altered source versions must be plainly marked as such, and must not be\r
29 ;     misrepresented as being the original software\r
30 ;  3. This notice may not be removed or altered from any source distribution.\r
31 ;\r
32 ;\r
33 ;\r
34 ;         http://www.zlib.net\r
35 ;         http://www.winimage.com/zLibDll\r
36 ;         http://www.muppetlabs.com/~breadbox/software/assembly.html\r
37 ;\r
38 ; to compile this file for infozip Zip, I use option:\r
39 ;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm\r
40 ;\r
41 ; to compile this file for zLib, I use option:\r
42 ;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm\r
43 ; Be carrefull to adapt zlib1222add below to your version of zLib\r
44 ;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change\r
45 ;    value of zlib1222add later)\r
46 ;\r
47 ; This file compile with Microsoft Macro Assembler (x64) for AMD64\r
48 ;\r
49 ;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK\r
50 ;\r
51 ;   (you can get Windows WDK with ml64 for AMD64 from\r
52 ;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)\r
53 ;\r
54 \r
55 \r
56 ;uInt longest_match(s, cur_match)\r
57 ;    deflate_state *s;\r
58 ;    IPos cur_match;                             /* current match */\r
59 .code\r
60 longest_match PROC\r
61 \r
62 \r
63 ;LocalVarsSize   equ 88\r
64  LocalVarsSize   equ 72\r
65 \r
66 ; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12\r
67 ; free register :  r14,r15\r
68 ; register can be saved : rsp\r
69 \r
70  chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len\r
71                                                  ; low word: s->wmask\r
72 ;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10\r
73 ;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11\r
74 ;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w\r
75 ;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx\r
76 ;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13\r
77 ;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d\r
78 ;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9\r
79 IFDEF INFOZIP\r
80 ELSE\r
81  nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size\r
82 ENDIF\r
83 \r
84 save_rdi        equ  rsp + 24 - LocalVarsSize\r
85 save_rsi        equ  rsp + 32 - LocalVarsSize\r
86 save_rbx        equ  rsp + 40 - LocalVarsSize\r
87 save_rbp        equ  rsp + 48 - LocalVarsSize\r
88 save_r12        equ  rsp + 56 - LocalVarsSize\r
89 save_r13        equ  rsp + 64 - LocalVarsSize\r
90 ;save_r14        equ  rsp + 72 - LocalVarsSize\r
91 ;save_r15        equ  rsp + 80 - LocalVarsSize\r
92 \r
93 \r
94 ; summary of register usage\r
95 ; scanend     ebx\r
96 ; scanendw    bx\r
97 ; chainlenwmask   edx\r
98 ; curmatch    rsi\r
99 ; curmatchd   esi\r
100 ; windowbestlen   r8\r
101 ; scanalign   r9\r
102 ; scanalignd  r9d\r
103 ; window      r10\r
104 ; bestlen     r11\r
105 ; bestlend    r11d\r
106 ; scanstart   r12d\r
107 ; scanstartw  r12w\r
108 ; scan        r13\r
109 ; nicematch   r14d\r
110 ; limit       r15\r
111 ; limitd      r15d\r
112 ; prev        rcx\r
113 \r
114 ;  all the +4 offsets are due to the addition of pending_buf_size (in zlib\r
115 ;  in the deflate_state structure since the asm code was first written\r
116 ;  (if you compile with zlib 1.0.4 or older, remove the +4).\r
117 ;  Note : these value are good with a 8 bytes boundary pack structure\r
118 \r
119 \r
120     MAX_MATCH           equ     258\r
121     MIN_MATCH           equ     3\r
122     MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)\r
123 \r
124 \r
125 ;;; Offsets for fields in the deflate_state structure. These numbers\r
126 ;;; are calculated from the definition of deflate_state, with the\r
127 ;;; assumption that the compiler will dword-align the fields. (Thus,\r
128 ;;; changing the definition of deflate_state could easily cause this\r
129 ;;; program to crash horribly, without so much as a warning at\r
130 ;;; compile time. Sigh.)\r
131 \r
132 ;  all the +zlib1222add offsets are due to the addition of fields\r
133 ;  in zlib in the deflate_state structure since the asm code was first written\r
134 ;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
135 ;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
136 ;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
137 \r
138 \r
139 IFDEF INFOZIP\r
140 \r
141 _DATA   SEGMENT\r
142 COMM    window_size:DWORD\r
143 ; WMask ; 7fff\r
144 COMM    window:BYTE:010040H\r
145 COMM    prev:WORD:08000H\r
146 ; MatchLen : unused\r
147 ; PrevMatch : unused\r
148 COMM    strstart:DWORD\r
149 COMM    match_start:DWORD\r
150 ; Lookahead : ignore\r
151 COMM    prev_length:DWORD ; PrevLen\r
152 COMM    max_chain_length:DWORD\r
153 COMM    good_match:DWORD\r
154 COMM    nice_match:DWORD\r
155 prev_ad equ OFFSET prev\r
156 window_ad equ OFFSET window\r
157 nicematch equ nice_match\r
158 _DATA ENDS\r
159 WMask equ 07fffh\r
160 \r
161 ELSE\r
162 \r
163   IFNDEF zlib1222add\r
164     zlib1222add equ 8\r
165   ENDIF\r
166 dsWSize         equ 56+zlib1222add+(zlib1222add/2)\r
167 dsWMask         equ 64+zlib1222add+(zlib1222add/2)\r
168 dsWindow        equ 72+zlib1222add\r
169 dsPrev          equ 88+zlib1222add\r
170 dsMatchLen      equ 128+zlib1222add\r
171 dsPrevMatch     equ 132+zlib1222add\r
172 dsStrStart      equ 140+zlib1222add\r
173 dsMatchStart    equ 144+zlib1222add\r
174 dsLookahead     equ 148+zlib1222add\r
175 dsPrevLen       equ 152+zlib1222add\r
176 dsMaxChainLen   equ 156+zlib1222add\r
177 dsGoodMatch     equ 172+zlib1222add\r
178 dsNiceMatch     equ 176+zlib1222add\r
179 \r
180 window_size     equ [ rcx + dsWSize]\r
181 WMask           equ [ rcx + dsWMask]\r
182 window_ad       equ [ rcx + dsWindow]\r
183 prev_ad         equ [ rcx + dsPrev]\r
184 strstart        equ [ rcx + dsStrStart]\r
185 match_start     equ [ rcx + dsMatchStart]\r
186 Lookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip\r
187 prev_length     equ [ rcx + dsPrevLen]\r
188 max_chain_length equ [ rcx + dsMaxChainLen]\r
189 good_match      equ [ rcx + dsGoodMatch]\r
190 nice_match      equ [ rcx + dsNiceMatch]\r
191 ENDIF\r
192 \r
193 ; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)\r
194 \r
195 ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and\r
196 ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp\r
197 ;\r
198 ; All registers must be preserved across the call, except for\r
199 ;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.\r
200 \r
201 \r
202 \r
203 ;;; Save registers that the compiler may be using, and adjust esp to\r
204 ;;; make room for our stack frame.\r
205 \r
206 \r
207 ;;; Retrieve the function arguments. r8d will hold cur_match\r
208 ;;; throughout the entire function. edx will hold the pointer to the\r
209 ;;; deflate_state structure during the function's setup (before\r
210 ;;; entering the main loop.\r
211 \r
212 ; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)\r
213 \r
214 ; this clear high 32 bits of r8, which can be garbage in both r8 and rdx\r
215 \r
216         mov [save_rdi],rdi\r
217         mov [save_rsi],rsi\r
218         mov [save_rbx],rbx\r
219         mov [save_rbp],rbp\r
220 IFDEF INFOZIP\r
221         mov r8d,ecx\r
222 ELSE\r
223         mov r8d,edx\r
224 ENDIF\r
225         mov [save_r12],r12\r
226         mov [save_r13],r13\r
227 ;        mov [save_r14],r14\r
228 ;        mov [save_r15],r15\r
229 \r
230 \r
231 ;;; uInt wmask = s->w_mask;\r
232 ;;; unsigned chain_length = s->max_chain_length;\r
233 ;;; if (s->prev_length >= s->good_match) {\r
234 ;;;     chain_length >>= 2;\r
235 ;;; }\r
236 \r
237         mov edi, prev_length\r
238         mov esi, good_match\r
239         mov eax, WMask\r
240         mov ebx, max_chain_length\r
241         cmp edi, esi\r
242         jl  LastMatchGood\r
243         shr ebx, 2\r
244 LastMatchGood:\r
245 \r
246 ;;; chainlen is decremented once beforehand so that the function can\r
247 ;;; use the sign flag instead of the zero flag for the exit test.\r
248 ;;; It is then shifted into the high word, to make room for the wmask\r
249 ;;; value, which it will always accompany.\r
250 \r
251         dec ebx\r
252         shl ebx, 16\r
253         or  ebx, eax\r
254 \r
255 ;;; on zlib only\r
256 ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
257 \r
258 IFDEF INFOZIP\r
259         mov [chainlenwmask], ebx\r
260 ; on infozip nice_match = [nice_match]\r
261 ELSE\r
262         mov eax, nice_match\r
263         mov [chainlenwmask], ebx\r
264         mov r10d, Lookahead\r
265         cmp r10d, eax\r
266         cmovnl r10d, eax\r
267         mov [nicematch],r10d\r
268 ENDIF\r
269 \r
270 ;;; register Bytef *scan = s->window + s->strstart;\r
271         mov r10, window_ad\r
272         mov ebp, strstart\r
273         lea r13, [r10 + rbp]\r
274 \r
275 ;;; Determine how many bytes the scan ptr is off from being\r
276 ;;; dword-aligned.\r
277 \r
278          mov r9,r13\r
279          neg r13\r
280          and r13,3\r
281 \r
282 ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
283 ;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;\r
284 IFDEF INFOZIP\r
285         mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))\r
286 ELSE\r
287         mov eax, window_size\r
288         sub eax, MIN_LOOKAHEAD\r
289 ENDIF\r
290         xor edi,edi\r
291         sub ebp, eax\r
292 \r
293         mov r11d, prev_length\r
294 \r
295         cmovng ebp,edi\r
296 \r
297 ;;; int best_len = s->prev_length;\r
298 \r
299 \r
300 ;;; Store the sum of s->window + best_len in esi locally, and in esi.\r
301 \r
302        lea  rsi,[r10+r11]\r
303 \r
304 ;;; register ush scan_start = *(ushf*)scan;\r
305 ;;; register ush scan_end   = *(ushf*)(scan+best_len-1);\r
306 ;;; Posf *prev = s->prev;\r
307 \r
308         movzx r12d,word ptr [r9]\r
309         movzx ebx, word ptr [r9 + r11 - 1]\r
310 \r
311         mov rdi, prev_ad\r
312 \r
313 ;;; Jump into the main loop.\r
314 \r
315         mov edx, [chainlenwmask]\r
316 \r
317         cmp bx,word ptr [rsi + r8 - 1]\r
318         jz  LookupLoopIsZero\r
319 \r
320 LookupLoop1:\r
321         and r8d, edx\r
322 \r
323         movzx   r8d, word ptr [rdi + r8*2]\r
324         cmp r8d, ebp\r
325         jbe LeaveNow\r
326         sub edx, 00010000h\r
327         js  LeaveNow\r
328 \r
329 LoopEntry1:\r
330         cmp bx,word ptr [rsi + r8 - 1]\r
331         jz  LookupLoopIsZero\r
332 \r
333 LookupLoop2:\r
334         and r8d, edx\r
335 \r
336         movzx   r8d, word ptr [rdi + r8*2]\r
337         cmp r8d, ebp\r
338         jbe LeaveNow\r
339         sub edx, 00010000h\r
340         js  LeaveNow\r
341 \r
342 LoopEntry2:\r
343         cmp bx,word ptr [rsi + r8 - 1]\r
344         jz  LookupLoopIsZero\r
345 \r
346 LookupLoop4:\r
347         and r8d, edx\r
348 \r
349         movzx   r8d, word ptr [rdi + r8*2]\r
350         cmp r8d, ebp\r
351         jbe LeaveNow\r
352         sub edx, 00010000h\r
353         js  LeaveNow\r
354 \r
355 LoopEntry4:\r
356 \r
357         cmp bx,word ptr [rsi + r8 - 1]\r
358         jnz LookupLoop1\r
359         jmp LookupLoopIsZero\r
360 \r
361 \r
362 ;;; do {\r
363 ;;;     match = s->window + cur_match;\r
364 ;;;     if (*(ushf*)(match+best_len-1) != scan_end ||\r
365 ;;;         *(ushf*)match != scan_start) continue;\r
366 ;;;     [...]\r
367 ;;; } while ((cur_match = prev[cur_match & wmask]) > limit\r
368 ;;;          && --chain_length != 0);\r
369 ;;;\r
370 ;;; Here is the inner loop of the function. The function will spend the\r
371 ;;; majority of its time in this loop, and majority of that time will\r
372 ;;; be spent in the first ten instructions.\r
373 ;;;\r
374 ;;; Within this loop:\r
375 ;;; ebx = scanend\r
376 ;;; r8d = curmatch\r
377 ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
378 ;;; esi = windowbestlen - i.e., (window + bestlen)\r
379 ;;; edi = prev\r
380 ;;; ebp = limit\r
381 \r
382 LookupLoop:\r
383         and r8d, edx\r
384 \r
385         movzx   r8d, word ptr [rdi + r8*2]\r
386         cmp r8d, ebp\r
387         jbe LeaveNow\r
388         sub edx, 00010000h\r
389         js  LeaveNow\r
390 \r
391 LoopEntry:\r
392 \r
393         cmp bx,word ptr [rsi + r8 - 1]\r
394         jnz LookupLoop1\r
395 LookupLoopIsZero:\r
396         cmp     r12w, word ptr [r10 + r8]\r
397         jnz LookupLoop1\r
398 \r
399 \r
400 ;;; Store the current value of chainlen.\r
401         mov [chainlenwmask], edx\r
402 \r
403 ;;; Point edi to the string under scrutiny, and esi to the string we\r
404 ;;; are hoping to match it up with. In actuality, esi and edi are\r
405 ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is\r
406 ;;; initialized to -(MAX_MATCH_8 - scanalign).\r
407 \r
408         lea rsi,[r8+r10]\r
409         mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)\r
410         lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]\r
411         lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]\r
412 \r
413         prefetcht1 [rsi+rdx]\r
414         prefetcht1 [rdi+rdx]\r
415 \r
416 \r
417 ;;; Test the strings for equality, 8 bytes at a time. At the end,\r
418 ;;; adjust rdx so that it is offset to the exact byte that mismatched.\r
419 ;;;\r
420 ;;; We already know at this point that the first three bytes of the\r
421 ;;; strings match each other, and they can be safely passed over before\r
422 ;;; starting the compare loop. So what this code does is skip over 0-3\r
423 ;;; bytes, as much as necessary in order to dword-align the edi\r
424 ;;; pointer. (rsi will still be misaligned three times out of four.)\r
425 ;;;\r
426 ;;; It should be confessed that this loop usually does not represent\r
427 ;;; much of the total running time. Replacing it with a more\r
428 ;;; straightforward "rep cmpsb" would not drastically degrade\r
429 ;;; performance.\r
430 \r
431 \r
432 LoopCmps:\r
433         mov rax, [rsi + rdx]\r
434         xor rax, [rdi + rdx]\r
435         jnz LeaveLoopCmps\r
436 \r
437         mov rax, [rsi + rdx + 8]\r
438         xor rax, [rdi + rdx + 8]\r
439         jnz LeaveLoopCmps8\r
440 \r
441 \r
442         mov rax, [rsi + rdx + 8+8]\r
443         xor rax, [rdi + rdx + 8+8]\r
444         jnz LeaveLoopCmps16\r
445 \r
446         add rdx,8+8+8\r
447 \r
448         jnz short LoopCmps\r
449         jmp short LenMaximum\r
450 LeaveLoopCmps16: add rdx,8\r
451 LeaveLoopCmps8: add rdx,8\r
452 LeaveLoopCmps:\r
453 \r
454         test    eax, 0000FFFFh\r
455         jnz LenLower\r
456 \r
457         test eax,0ffffffffh\r
458 \r
459         jnz LenLower32\r
460 \r
461         add rdx,4\r
462         shr rax,32\r
463         or ax,ax\r
464         jnz LenLower\r
465 \r
466 LenLower32:\r
467         shr eax,16\r
468         add rdx,2\r
469 LenLower:   sub al, 1\r
470         adc rdx, 0\r
471 ;;; Calculate the length of the match. If it is longer than MAX_MATCH,\r
472 ;;; then automatically accept it as the best possible match and leave.\r
473 \r
474         lea rax, [rdi + rdx]\r
475         sub rax, r9\r
476         cmp eax, MAX_MATCH\r
477         jge LenMaximum\r
478 \r
479 ;;; If the length of the match is not longer than the best match we\r
480 ;;; have so far, then forget it and return to the lookup loop.\r
481 ;///////////////////////////////////\r
482 \r
483         cmp eax, r11d\r
484         jg  LongerMatch\r
485 \r
486         lea rsi,[r10+r11]\r
487 \r
488         mov rdi, prev_ad\r
489         mov edx, [chainlenwmask]\r
490         jmp LookupLoop\r
491 \r
492 ;;;         s->match_start = cur_match;\r
493 ;;;         best_len = len;\r
494 ;;;         if (len >= nice_match) break;\r
495 ;;;         scan_end = *(ushf*)(scan+best_len-1);\r
496 \r
497 LongerMatch:\r
498         mov r11d, eax\r
499         mov match_start, r8d\r
500         cmp eax, [nicematch]\r
501         jge LeaveNow\r
502 \r
503         lea rsi,[r10+rax]\r
504 \r
505         movzx   ebx, word ptr [r9 + rax - 1]\r
506         mov rdi, prev_ad\r
507         mov edx, [chainlenwmask]\r
508         jmp LookupLoop\r
509 \r
510 ;;; Accept the current string, with the maximum possible length.\r
511 \r
512 LenMaximum:\r
513         mov r11d,MAX_MATCH\r
514         mov match_start, r8d\r
515 \r
516 ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\r
517 ;;; return s->lookahead;\r
518 \r
519 LeaveNow:\r
520 IFDEF INFOZIP\r
521         mov eax,r11d\r
522 ELSE\r
523         mov eax, Lookahead\r
524         cmp r11d, eax\r
525         cmovng eax, r11d\r
526 ENDIF\r
527 \r
528 ;;; Restore the stack and return from whence we came.\r
529 \r
530 \r
531         mov rsi,[save_rsi]\r
532         mov rdi,[save_rdi]\r
533         mov rbx,[save_rbx]\r
534         mov rbp,[save_rbp]\r
535         mov r12,[save_r12]\r
536         mov r13,[save_r13]\r
537 ;        mov r14,[save_r14]\r
538 ;        mov r15,[save_r15]\r
539 \r
540 \r
541         ret 0\r
542 ; please don't remove this string !\r
543 ; Your can freely use gvmat64 in any free or commercial app\r
544 ; but it is far better don't remove the string in the binary!\r
545     db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0\r
546 longest_match   ENDP\r
547 \r
548 match_init PROC\r
549   ret 0\r
550 match_init ENDP\r
551 \r
552 \r
553 END\r