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