1 ; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
\r
2 ; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
\r
3 ; File written by Gilles Vollant, by modifiying the longest_match
\r
4 ; from Jean-loup Gailly in deflate.c
\r
6 ; http://www.zlib.net
\r
7 ; http://www.winimage.com/zLibDll
\r
8 ; http://www.muppetlabs.com/~breadbox/software/assembly.html
\r
10 ; For Visual C++ 4.x and higher and ML 6.x and higher
\r
11 ; ml.exe is in directory \MASM611C of Win95 DDK
\r
12 ; ml.exe is also distributed in http://www.masm32.com/masmdl.htm
\r
13 ; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
\r
15 ; this file contain two implementation of longest_match
\r
17 ; longest_match_7fff : written 1996 by Gilles Vollant optimized for
\r
18 ; first Pentium. Assume s->w_mask == 0x7fff
\r
19 ; longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
\r
21 ; for using an seembly version of longest_match, you need define ASMV in project
\r
22 ; There is two way in using gvmat32.asm
\r
24 ; A) Suggested method
\r
25 ; if you want include both longest_match_7fff and longest_match_686
\r
26 ; compile the asm file running
\r
27 ; ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
\r
28 ; and include gvmat32c.c in your project
\r
29 ; if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
\r
30 ; longest_match_7fff will be used
\r
31 ; if you have a more modern CPU (Pentium Pro, II and higher)
\r
32 ; longest_match_686 will be used
\r
33 ; on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
\r
34 ; but this is not a sitation you'll find often
\r
37 ; if you are not interresed in old cpu performance and want the smaller
\r
40 ; compile the asm file running
\r
41 ; ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
\r
42 ; and do not include gvmat32c.c in your project (ou define also
\r
45 ; note : as I known, longest_match_686 is very faster than longest_match_7fff
\r
46 ; on pentium Pro/II/III, faster (but less) in P4, but it seem
\r
47 ; longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
\r
49 ; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
\r
51 ;uInt longest_match_7fff(s, cur_match)
\r
53 ; IPos cur_match; /* current match */
\r
56 cur_match equ dword ptr[esp+NbStack-0]
\r
57 str_s equ dword ptr[esp+NbStack-4]
\r
58 ; 5 dword on top (ret,ebp,esi,edi,ebx)
\r
59 adrret equ dword ptr[esp+NbStack-8]
\r
60 pushebp equ dword ptr[esp+NbStack-12]
\r
61 pushedi equ dword ptr[esp+NbStack-16]
\r
62 pushesi equ dword ptr[esp+NbStack-20]
\r
63 pushebx equ dword ptr[esp+NbStack-24]
\r
65 chain_length equ dword ptr [esp+NbStack-28]
\r
66 limit equ dword ptr [esp+NbStack-32]
\r
67 best_len equ dword ptr [esp+NbStack-36]
\r
68 window equ dword ptr [esp+NbStack-40]
\r
69 prev equ dword ptr [esp+NbStack-44]
\r
70 scan_start equ word ptr [esp+NbStack-48]
\r
71 wmask equ dword ptr [esp+NbStack-52]
\r
72 match_start_ptr equ dword ptr [esp+NbStack-56]
\r
73 nice_match equ dword ptr [esp+NbStack-60]
\r
74 scan equ dword ptr [esp+NbStack-64]
\r
76 windowlen equ dword ptr [esp+NbStack-68]
\r
77 match_start equ dword ptr [esp+NbStack-72]
\r
78 strend equ dword ptr [esp+NbStack-76]
\r
79 NbStackAdd equ (NbStack-24)
\r
88 ; all the +zlib1222add offsets are due to the addition of fields
\r
89 ; in zlib in the deflate_state structure since the asm code was first written
\r
90 ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
\r
91 ; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
\r
92 ; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
\r
96 ; Note : these value are good with a 8 bytes boundary pack structure
\r
97 dep_chain_length equ 74h+zlib1222add
\r
98 dep_window equ 30h+zlib1222add
\r
99 dep_strstart equ 64h+zlib1222add
\r
100 dep_prev_length equ 70h+zlib1222add
\r
101 dep_nice_match equ 88h+zlib1222add
\r
102 dep_w_size equ 24h+zlib1222add
\r
103 dep_prev equ 38h+zlib1222add
\r
104 dep_w_mask equ 2ch+zlib1222add
\r
105 dep_good_match equ 84h+zlib1222add
\r
106 dep_match_start equ 68h+zlib1222add
\r
107 dep_lookahead equ 6ch+zlib1222add
\r
113 IFDEF NOOLDPENTIUMCODE
\r
114 public longest_match
\r
117 public longest_match_7fff
\r
119 public longest_match_686
\r
122 IFDEF NOOLDPENTIUMCODE
\r
123 public _longest_match
\r
126 public _longest_match_7fff
\r
127 public _cpudetect32
\r
128 public _longest_match_686
\r
134 MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
\r
138 IFNDEF NOOLDPENTIUMCODE
\r
140 longest_match_7fff proc near
\r
142 _longest_match_7fff proc near
\r
156 ; initialize or check the variables used in match.asm.
\r
159 ; chain_length = s->max_chain_length
\r
160 ; if (prev_length>=good_match) chain_length >>= 2
\r
161 mov edx,[ebp+dep_chain_length]
\r
162 mov ebx,[ebp+dep_prev_length]
\r
163 cmp [ebp+dep_good_match],ebx
\r
167 ; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
\r
169 mov edi,[ebp+dep_nice_match]
\r
170 mov chain_length,edx
\r
171 mov eax,[ebp+dep_lookahead]
\r
173 ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
\r
174 jae nolookaheadnicematch
\r
176 nolookaheadnicematch:
\r
177 ; best_len = s->prev_length
\r
180 ; window = s->window
\r
181 mov esi,[ebp+dep_window]
\r
182 mov ecx,[ebp+dep_strstart]
\r
186 ; scan = window + strstart
\r
190 mov dx,word ptr [esi]
\r
191 ; bx = *(window+best_len-1)
\r
192 mov bx,word ptr [esi+ebx-1]
\r
193 add esi,MAX_MATCH-1
\r
194 ; scan_start = *scan
\r
196 ; strend = scan + MAX_MATCH-1
\r
198 ; bx = scan_end = *(window+best_len-1)
\r
200 ; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
\r
201 ; s->strstart - (IPos)MAX_DIST(s) : NIL;
\r
203 mov esi,[ebp+dep_w_size]
\r
204 sub esi,MIN_LOOKAHEAD
\r
205 ; here esi = MAX_DIST(s)
\r
213 mov edx,[ebp+dep_prev]
\r
217 mov edx,dword ptr [ebp+dep_match_start]
\r
220 mov match_start,edx
\r
227 ; windowlen = window + best_len -1
\r
233 ; here, in the loop
\r
234 ; eax = ax = cur_match
\r
238 ; edi = windowlen (window + best_len -1)
\r
242 ;// here; chain_length <=16
\r
244 add chain_length,16
\r
247 cmp word ptr[edi+eax],bx
\r
248 je normalbeg2noroll
\r
250 ; cur_match = prev[cur_match & wmask]
\r
252 mov ax,word ptr[esi+eax*2]
\r
253 ; if cur_match > limit, go to exitloop
\r
256 ; if --chain_length != 0, go to exitloop
\r
262 ; if (scan_start==*(cur_match+window)) goto normalbeg2
\r
263 cmp bp,word ptr[edx+eax]
\r
270 ; cur_match = prev[cur_match & wmask]
\r
272 mov ax,word ptr[esi+eax*2]
\r
273 ; if cur_match > limit, go to exitloop
\r
277 ; if --chain_length != 0, go to exitloop
\r
280 ; begin the main loop
\r
282 sub chain_length,16+1
\r
283 ; if chain_length <=16, don't use the unrolled loop
\r
284 jna normalbeg0add16
\r
287 cmp word ptr[edi+eax],bx
\r
292 mov ax,word ptr[esi+eax*2]
\r
295 cmp word ptr[edi+eax],bx
\r
300 maccn normalbeg2dc1
\r
303 maccn normalbeg2dc2
\r
306 maccn normalbeg2dc3
\r
309 maccn normalbeg2dc4
\r
312 maccn normalbeg2dc5
\r
315 maccn normalbeg2dc6
\r
318 maccn normalbeg2dc7
\r
321 maccn normalbeg2dc8
\r
324 maccn normalbeg2dc9
\r
327 maccn normalbeg2dc10
\r
330 maccn short normalbeg2dc11
\r
333 maccn short normalbeg2dc12
\r
336 maccn short normalbeg2dc13
\r
339 maccn short normalbeg2dc14
\r
342 maccn short normalbeg2dc15
\r
346 mov ax,word ptr[esi+eax*2]
\r
350 sub chain_length,16
\r
352 jmp normalbeg0add16
\r
354 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
356 normbeg MACRO rcontlab,valsub
\r
357 ; if we are here, we know that *(match+best_len-1) == scan_end
\r
358 cmp bp,word ptr[edx+eax]
\r
359 ; if (match != scan_start) goto rcontlab
\r
361 ; calculate the good chain_length, and we'll compare scan and match string
\r
362 add chain_length,16-valsub
\r
368 normbeg rcontloop11,11
\r
371 normbeg short rcontloop12,12
\r
374 normbeg short rcontloop13,13
\r
377 normbeg short rcontloop14,14
\r
380 normbeg short rcontloop15,15
\r
383 normbeg rcontloop10,10
\r
386 normbeg rcontloop9,9
\r
389 normbeg rcontloop8,8
\r
392 normbeg rcontloop7,7
\r
395 normbeg rcontloop6,6
\r
398 normbeg rcontloop5,5
\r
401 normbeg rcontloop4,4
\r
404 normbeg rcontloop3,3
\r
407 normbeg rcontloop2,2
\r
410 normbeg rcontloop1,1
\r
413 normbeg rcontloop0,0
\r
416 ; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
\r
421 cmp bp,word ptr[edi+eax]
\r
422 jne contloop3 ; if *(ushf*)match != scan_start, continue
\r
425 ; if we are here, we know that *(match+best_len-1) == scan_end
\r
426 ; and (match == scan_start)
\r
429 mov esi,scan ; esi = scan
\r
430 add edi,eax ; edi = window + cur_match = match
\r
432 mov edx,[esi+3] ; compare manually dword at match+3
\r
433 xor edx,[edi+3] ; and scan +3
\r
435 jz begincompare ; if equal, go to long compare
\r
437 ; we will determine the unmatch byte and calculate len (in esi)
\r
458 ; here we now scan and match begin same
\r
461 mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
\r
462 repe cmpsd ; loop until mismatch
\r
464 je trfin ; go to trfin if not unmatch
\r
465 ; we determine the unmatch byte
\r
483 sub esi,scan ; esi = len
\r
485 ; here we have finised compare, and esi contain len of equal string
\r
486 cmp esi,best_len ; if len > best_len, go newbestlen
\r
487 ja short newbestlen
\r
488 ; now we restore edx, ecx and esi, for the big loop
\r
495 mov best_len,esi ; len become best_len
\r
497 mov match_start,eax ; save new position as match_start
\r
498 cmp esi,nice_match ; if best_len >= nice_match, exit
\r
501 mov edx,window ; restore edx=window
\r
506 mov windowlen,esi ; windowlen = window + best_len-1
\r
507 mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
\r
509 ; now we restore ecx and esi, for the big loop :
\r
515 ; exit : s->match_start=match_start
\r
516 mov ebx,match_start
\r
519 mov dword ptr [ebp+dep_match_start],ebx
\r
520 mov eax,dword ptr [ebp+dep_lookahead]
\r
525 ; return min(best_len,s->lookahead)
\r
527 ; restore stack and register ebx,esi,edi,ebp
\r
536 ; please don't remove this string !
\r
537 ; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
\r
538 db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
\r
543 longest_match_7fff endp
\r
545 _longest_match_7fff endp
\r
550 cpudetect32 proc near
\r
552 _cpudetect32 proc near
\r
557 pushfd ; push original EFLAGS
\r
558 pop eax ; get original EFLAGS
\r
559 mov ecx, eax ; save original EFLAGS
\r
560 xor eax, 40000h ; flip AC bit in EFLAGS
\r
561 push eax ; save new EFLAGS value on stack
\r
562 popfd ; replace current EFLAGS value
\r
563 pushfd ; get new EFLAGS
\r
564 pop eax ; store new EFLAGS in EAX
\r
565 xor eax, ecx ; can
\92t toggle AC bit, processor=80386
\r
566 jz end_cpu_is_386 ; jump if 80386 processor
\r
568 popfd ; restore AC bit in EFLAGS first
\r
574 mov eax, ecx ; get original EFLAGS
\r
575 xor eax, 200000h ; flip ID bit in EFLAGS
\r
576 push eax ; save new EFLAGS value on stack
\r
577 popfd ; replace current EFLAGS value
\r
578 pushfd ; get new EFLAGS
\r
579 pop eax ; store new EFLAGS in EAX
\r
580 popfd ; restore original EFLAGS
\r
581 xor eax, ecx ; can
\92t toggle ID bit,
\r
582 je is_old_486 ; processor=old
\r
608 MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1)
\r
609 MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h)
\r
612 ;;; stack frame offsets
\r
614 chainlenwmask equ esp + 0 ; high word: current chain len
\r
615 ; low word: s->wmask
\r
616 window equ esp + 4 ; local copy of s->window
\r
617 windowbestlen equ esp + 8 ; s->window + bestlen
\r
618 scanstart equ esp + 16 ; first two bytes of string
\r
619 scanend equ esp + 12 ; last two bytes of string
\r
620 scanalign equ esp + 20 ; dword-misalignment of string
\r
621 nicematch equ esp + 24 ; a good enough match size
\r
622 bestlen equ esp + 28 ; size of best match so far
\r
623 scan equ esp + 32 ; ptr to string wanting match
\r
625 LocalVarsSize equ 36
\r
626 ; saved ebx byte esp + 36
\r
627 ; saved edi byte esp + 40
\r
628 ; saved esi byte esp + 44
\r
629 ; saved ebp byte esp + 48
\r
630 ; return address byte esp + 52
\r
631 deflatestate equ esp + 56 ; the function arguments
\r
632 curmatch equ esp + 60
\r
634 ;;; Offsets for fields in the deflate_state structure. These numbers
\r
635 ;;; are calculated from the definition of deflate_state, with the
\r
636 ;;; assumption that the compiler will dword-align the fields. (Thus,
\r
637 ;;; changing the definition of deflate_state could easily cause this
\r
638 ;;; program to crash horribly, without so much as a warning at
\r
639 ;;; compile time. Sigh.)
\r
641 dsWSize equ 36+zlib1222add
\r
642 dsWMask equ 44+zlib1222add
\r
643 dsWindow equ 48+zlib1222add
\r
644 dsPrev equ 56+zlib1222add
\r
645 dsMatchLen equ 88+zlib1222add
\r
646 dsPrevMatch equ 92+zlib1222add
\r
647 dsStrStart equ 100+zlib1222add
\r
648 dsMatchStart equ 104+zlib1222add
\r
649 dsLookahead equ 108+zlib1222add
\r
650 dsPrevLen equ 112+zlib1222add
\r
651 dsMaxChainLen equ 116+zlib1222add
\r
652 dsGoodMatch equ 132+zlib1222add
\r
653 dsNiceMatch equ 136+zlib1222add
\r
656 ;;; match.asm -- Pentium-Pro-optimized version of longest_match()
\r
657 ;;; Written for zlib 1.1.2
\r
658 ;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
\r
659 ;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
\r
661 ;;; This is free software; you can redistribute it and/or modify it
\r
662 ;;; under the terms of the GNU General Public License.
\r
664 ;GLOBAL _longest_match, _match_init
\r
669 ;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
\r
672 IFDEF NOOLDPENTIUMCODE
\r
674 longest_match proc near
\r
676 _longest_match proc near
\r
680 longest_match_686 proc near
\r
682 _longest_match_686 proc near
\r
686 ;;; Save registers that the compiler may be using, and adjust esp to
\r
687 ;;; make room for our stack frame.
\r
693 sub esp, LocalVarsSize
\r
695 ;;; Retrieve the function arguments. ecx will hold cur_match
\r
696 ;;; throughout the entire function. edx will hold the pointer to the
\r
697 ;;; deflate_state structure during the function's setup (before
\r
698 ;;; entering the main loop.
\r
700 mov edx, [deflatestate]
\r
701 mov ecx, [curmatch]
\r
703 ;;; uInt wmask = s->w_mask;
\r
704 ;;; unsigned chain_length = s->max_chain_length;
\r
705 ;;; if (s->prev_length >= s->good_match) {
\r
706 ;;; chain_length >>= 2;
\r
709 mov eax, [edx + dsPrevLen]
\r
710 mov ebx, [edx + dsGoodMatch]
\r
712 mov eax, [edx + dsWMask]
\r
713 mov ebx, [edx + dsMaxChainLen]
\r
718 ;;; chainlen is decremented once beforehand so that the function can
\r
719 ;;; use the sign flag instead of the zero flag for the exit test.
\r
720 ;;; It is then shifted into the high word, to make room for the wmask
\r
721 ;;; value, which it will always accompany.
\r
726 mov [chainlenwmask], ebx
\r
728 ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
\r
730 mov eax, [edx + dsNiceMatch]
\r
731 mov ebx, [edx + dsLookahead]
\r
735 LookaheadLess: mov [nicematch], ebx
\r
737 ;;; register Bytef *scan = s->window + s->strstart;
\r
739 mov esi, [edx + dsWindow]
\r
741 mov ebp, [edx + dsStrStart]
\r
742 lea edi, [esi + ebp]
\r
745 ;;; Determine how many bytes the scan ptr is off from being
\r
751 mov [scanalign], eax
\r
753 ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
\r
754 ;;; s->strstart - (IPos)MAX_DIST(s) : NIL;
\r
756 mov eax, [edx + dsWSize]
\r
757 sub eax, MIN_LOOKAHEAD
\r
763 ;;; int best_len = s->prev_length;
\r
765 mov eax, [edx + dsPrevLen]
\r
768 ;;; Store the sum of s->window + best_len in esi locally, and in esi.
\r
771 mov [windowbestlen], esi
\r
773 ;;; register ush scan_start = *(ushf*)scan;
\r
774 ;;; register ush scan_end = *(ushf*)(scan+best_len-1);
\r
775 ;;; Posf *prev = s->prev;
\r
777 movzx ebx, word ptr [edi]
\r
778 mov [scanstart], ebx
\r
779 movzx ebx, word ptr [edi + eax - 1]
\r
781 mov edi, [edx + dsPrev]
\r
783 ;;; Jump into the main loop.
\r
785 mov edx, [chainlenwmask]
\r
786 jmp short LoopEntry
\r
791 ;;; match = s->window + cur_match;
\r
792 ;;; if (*(ushf*)(match+best_len-1) != scan_end ||
\r
793 ;;; *(ushf*)match != scan_start) continue;
\r
795 ;;; } while ((cur_match = prev[cur_match & wmask]) > limit
\r
796 ;;; && --chain_length != 0);
\r
798 ;;; Here is the inner loop of the function. The function will spend the
\r
799 ;;; majority of its time in this loop, and majority of that time will
\r
800 ;;; be spent in the first ten instructions.
\r
802 ;;; Within this loop:
\r
805 ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
\r
806 ;;; esi = windowbestlen - i.e., (window + bestlen)
\r
812 movzx ecx, word ptr [edi + ecx*2]
\r
817 LoopEntry: movzx eax, word ptr [esi + ecx - 1]
\r
821 movzx eax, word ptr [eax + ecx]
\r
822 cmp eax, [scanstart]
\r
825 ;;; Store the current value of chainlen.
\r
827 mov [chainlenwmask], edx
\r
829 ;;; Point edi to the string under scrutiny, and esi to the string we
\r
830 ;;; are hoping to match it up with. In actuality, esi and edi are
\r
831 ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
\r
832 ;;; initialized to -(MAX_MATCH_8 - scanalign).
\r
837 mov eax, [scanalign]
\r
838 mov edx, 0fffffef8h; -(MAX_MATCH_8)
\r
839 lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
\r
840 lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
\r
842 ;;; Test the strings for equality, 8 bytes at a time. At the end,
\r
843 ;;; adjust edx so that it is offset to the exact byte that mismatched.
\r
845 ;;; We already know at this point that the first three bytes of the
\r
846 ;;; strings match each other, and they can be safely passed over before
\r
847 ;;; starting the compare loop. So what this code does is skip over 0-3
\r
848 ;;; bytes, as much as necessary in order to dword-align the edi
\r
849 ;;; pointer. (esi will still be misaligned three times out of four.)
\r
851 ;;; It should be confessed that this loop usually does not represent
\r
852 ;;; much of the total running time. Replacing it with a more
\r
853 ;;; straightforward "rep cmpsb" would not drastically degrade
\r
857 mov eax, [esi + edx]
\r
858 xor eax, [edi + edx]
\r
860 mov eax, [esi + edx + 4]
\r
861 xor eax, [edi + edx + 4]
\r
865 jmp short LenMaximum
\r
866 LeaveLoopCmps4: add edx, 4
\r
867 LeaveLoopCmps: test eax, 0000FFFFh
\r
871 LenLower: sub al, 1
\r
874 ;;; Calculate the length of the match. If it is longer than MAX_MATCH,
\r
875 ;;; then automatically accept it as the best possible match and leave.
\r
877 lea eax, [edi + edx]
\r
883 ;;; If the length of the match is not longer than the best match we
\r
884 ;;; have so far, then forget it and return to the lookup loop.
\r
886 mov edx, [deflatestate]
\r
890 mov esi, [windowbestlen]
\r
891 mov edi, [edx + dsPrev]
\r
893 mov edx, [chainlenwmask]
\r
896 ;;; s->match_start = cur_match;
\r
897 ;;; best_len = len;
\r
898 ;;; if (len >= nice_match) break;
\r
899 ;;; scan_end = *(ushf*)(scan+best_len-1);
\r
901 LongerMatch: mov ebx, [nicematch]
\r
903 mov [edx + dsMatchStart], ecx
\r
908 mov [windowbestlen], esi
\r
909 movzx ebx, word ptr [edi + eax - 1]
\r
910 mov edi, [edx + dsPrev]
\r
912 mov edx, [chainlenwmask]
\r
915 ;;; Accept the current string, with the maximum possible length.
\r
917 LenMaximum: mov edx, [deflatestate]
\r
918 mov dword ptr [bestlen], MAX_MATCH
\r
919 mov [edx + dsMatchStart], ecx
\r
921 ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
\r
922 ;;; return s->lookahead;
\r
925 mov edx, [deflatestate]
\r
927 mov eax, [edx + dsLookahead]
\r
933 ;;; Restore the stack and return from whence we came.
\r
935 add esp, LocalVarsSize
\r
942 ; please don't remove this string !
\r
943 ; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
\r
944 db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
\r
947 IFDEF NOOLDPENTIUMCODE
\r
951 _longest_match endp
\r
955 match_init proc near
\r
959 _match_init proc near
\r
965 longest_match_686 endp
\r
967 _longest_match_686 endp
\r