2 ; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
3 ; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
4 ; File written by Gilles Vollant, by modifiying the longest_match
5 ; from Jean-loup Gailly in deflate.c
6 ; It need wmask == 0x7fff
7 ; (assembly code is faster with a fixed wmask)
9 ; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)
10 ; I compile with : "ml /coff /Zi /c gvmat32.asm"
13 ;uInt longest_match_7fff(s, cur_match)
15 ; IPos cur_match; /* current match */
18 cur_match equ dword ptr[esp+NbStack-0]
19 str_s equ dword ptr[esp+NbStack-4]
20 ; 5 dword on top (ret,ebp,esi,edi,ebx)
21 adrret equ dword ptr[esp+NbStack-8]
22 pushebp equ dword ptr[esp+NbStack-12]
23 pushedi equ dword ptr[esp+NbStack-16]
24 pushesi equ dword ptr[esp+NbStack-20]
25 pushebx equ dword ptr[esp+NbStack-24]
27 chain_length equ dword ptr [esp+NbStack-28]
28 limit equ dword ptr [esp+NbStack-32]
29 best_len equ dword ptr [esp+NbStack-36]
30 window equ dword ptr [esp+NbStack-40]
31 prev equ dword ptr [esp+NbStack-44]
32 scan_start equ word ptr [esp+NbStack-48]
33 wmask equ dword ptr [esp+NbStack-52]
34 match_start_ptr equ dword ptr [esp+NbStack-56]
35 nice_match equ dword ptr [esp+NbStack-60]
36 scan equ dword ptr [esp+NbStack-64]
38 windowlen equ dword ptr [esp+NbStack-68]
39 match_start equ dword ptr [esp+NbStack-72]
40 strend equ dword ptr [esp+NbStack-76]
41 NbStackAdd equ (NbStack-24)
50 ; all the +4 offsets are due to the addition of pending_buf_size (in zlib
51 ; in the deflate_state structure since the asm code was first written
52 ; (if you compile with zlib 1.0.4 or older, remove the +4).
53 ; Note : these value are good with a 8 bytes boundary pack structure
54 dep_chain_length equ 70h+4
56 dep_strstart equ 60h+4
57 dep_prev_length equ 6ch+4
58 dep_nice_match equ 84h+4
62 dep_good_match equ 80h+4
63 dep_match_start equ 64h+4
64 dep_lookahead equ 68h+4
70 public longest_match_7fff
73 public _longest_match_7fff
79 MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
88 ;_match_init proc near
95 longest_match_7fff proc near
97 _longest_match_7fff proc near
111 ; initialize or check the variables used in match.asm.
114 ; chain_length = s->max_chain_length
115 ; if (prev_length>=good_match) chain_length >>= 2
116 mov edx,[ebp+dep_chain_length]
117 mov ebx,[ebp+dep_prev_length]
118 cmp [ebp+dep_good_match],ebx
122 ; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
124 mov edi,[ebp+dep_nice_match]
126 mov eax,[ebp+dep_lookahead]
128 ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
129 jae nolookaheadnicematch
131 nolookaheadnicematch:
132 ; best_len = s->prev_length
136 mov esi,[ebp+dep_window]
137 mov ecx,[ebp+dep_strstart]
141 ; scan = window + strstart
145 mov dx,word ptr [esi]
146 ; bx = *(window+best_len-1)
147 mov bx,word ptr [esi+ebx-1]
151 ; strend = scan + MAX_MATCH-1
153 ; bx = scan_end = *(window+best_len-1)
155 ; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
156 ; s->strstart - (IPos)MAX_DIST(s) : NIL;
158 mov esi,[ebp+dep_w_size]
159 sub esi,MIN_LOOKAHEAD
160 ; here esi = MAX_DIST(s)
168 mov edx,[ebp+dep_prev]
172 mov edx,dword ptr [ebp+dep_match_start]
182 ; windowlen = window + best_len -1
189 ; eax = ax = cur_match
193 ; edi = windowlen (window + best_len -1)
197 ;// here; chain_length <=16
202 cmp word ptr[edi+eax],bx
205 ; cur_match = prev[cur_match & wmask]
207 mov ax,word ptr[esi+eax*2]
208 ; if cur_match > limit, go to exitloop
211 ; if --chain_length != 0, go to exitloop
217 ; if (scan_start==*(cur_match+window)) goto normalbeg2
218 cmp bp,word ptr[edx+eax]
225 ; cur_match = prev[cur_match & wmask]
227 mov ax,word ptr[esi+eax*2]
228 ; if cur_match > limit, go to exitloop
232 ; if --chain_length != 0, go to exitloop
235 ; begin the main loop
237 sub chain_length,16+1
238 ; if chain_length <=16, don't use the unrolled loop
242 cmp word ptr[edi+eax],bx
247 mov ax,word ptr[esi+eax*2]
250 cmp word ptr[edi+eax],bx
285 maccn short normalbeg2dc11
288 maccn short normalbeg2dc12
291 maccn short normalbeg2dc13
294 maccn short normalbeg2dc14
297 maccn short normalbeg2dc15
301 mov ax,word ptr[esi+eax*2]
309 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
311 normbeg MACRO rcontlab,valsub
312 ; if we are here, we know that *(match+best_len-1) == scan_end
313 cmp bp,word ptr[edx+eax]
314 ; if (match != scan_start) goto rcontlab
316 ; calculate the good chain_length, and we'll compare scan and match string
317 add chain_length,16-valsub
323 normbeg rcontloop11,11
326 normbeg short rcontloop12,12
329 normbeg short rcontloop13,13
332 normbeg short rcontloop14,14
335 normbeg short rcontloop15,15
338 normbeg rcontloop10,10
371 ; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
376 cmp bp,word ptr[edi+eax]
377 jne contloop3 ; if *(ushf*)match != scan_start, continue
380 ; if we are here, we know that *(match+best_len-1) == scan_end
381 ; and (match == scan_start)
384 mov esi,scan ; esi = scan
385 add edi,eax ; edi = window + cur_match = match
387 mov edx,[esi+3] ; compare manually dword at match+3
388 xor edx,[edi+3] ; and scan +3
390 jz begincompare ; if equal, go to long compare
392 ; we will determine the unmatch byte and calculate len (in esi)
413 ; here we now scan and match begin same
416 mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
417 repe cmpsd ; loop until mismatch
419 je trfin ; go to trfin if not unmatch
420 ; we determine the unmatch byte
438 sub esi,scan ; esi = len
440 ; here we have finised compare, and esi contain len of equal string
441 cmp esi,best_len ; if len > best_len, go newbestlen
443 ; now we restore edx, ecx and esi, for the big loop
450 mov best_len,esi ; len become best_len
452 mov match_start,eax ; save new position as match_start
453 cmp esi,nice_match ; if best_len >= nice_match, exit
456 mov edx,window ; restore edx=window
461 mov windowlen,esi ; windowlen = window + best_len-1
462 mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
464 ; now we restore ecx and esi, for the big loop :
470 ; exit : s->match_start=match_start
474 mov dword ptr [ebp+dep_match_start],ebx
475 mov eax,dword ptr [ebp+dep_lookahead]
480 ; return min(best_len,s->lookahead)
482 ; restore stack and register ebx,esi,edi,ebp
491 ; please don't remove this string !
492 ; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
493 db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
498 longest_match_7fff endp
500 _longest_match_7fff endp
505 cpudetect32 proc near
507 _cpudetect32 proc near
511 pushfd ; push original EFLAGS
512 pop eax ; get original EFLAGS
513 mov ecx, eax ; save original EFLAGS
514 xor eax, 40000h ; flip AC bit in EFLAGS
515 push eax ; save new EFLAGS value on stack
516 popfd ; replace current EFLAGS value
517 pushfd ; get new EFLAGS
518 pop eax ; store new EFLAGS in EAX
519 xor eax, ecx ; can
\92t toggle AC bit, processor=80386
520 jz end_cpu_is_386 ; jump if 80386 processor
522 popfd ; restore AC bit in EFLAGS first
528 mov eax, ecx ; get original EFLAGS
529 xor eax, 200000h ; flip ID bit in EFLAGS
530 push eax ; save new EFLAGS value on stack
531 popfd ; replace current EFLAGS value
532 pushfd ; get new EFLAGS
533 pop eax ; store new EFLAGS in EAX
534 popfd ; restore original EFLAGS
535 xor eax, ecx ; can
\92t toggle ID bit,
536 je is_old_486 ; processor=old