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’t 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’t toggle ID bit,
536 je is_old_486
; processor=old