which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
152 lines
5.9 KiB
NASM
Executable File
152 lines
5.9 KiB
NASM
Executable File
;
|
|
; Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly,
|
|
; Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko.
|
|
; Permission is granted to any individual or institution to use, copy, or
|
|
; redistribute this software so long as all of the original files are included,
|
|
; that it is not sold for profit, and that this copyright notice is retained.
|
|
;
|
|
; match32.asm by Jean-loup Gailly.
|
|
|
|
; match32.asm, optimized version of longest_match() in deflate.c
|
|
; To be used only with 32 bit flat model. To simplify the code, the option
|
|
; -DDYN_ALLOC is not supported.
|
|
; This file is only optional. If you don't have an assembler, use the
|
|
; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
|
|
; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
|
|
; assembled with an equivalent -DWSIZE=<whatever>.
|
|
;
|
|
; Win32 (Windows NT) version - 1994/04/13 by Steve Salisbury
|
|
; * works with Microsoft MASM 6.1X and Microsoft Visual C++ / 32-bit edition
|
|
|
|
.386p
|
|
|
|
name match
|
|
.MODEL FLAT
|
|
|
|
_BSS segment
|
|
extrn _match_start : dword
|
|
extrn _prev_length : dword
|
|
extrn _good_match : dword
|
|
extrn _strstart : dword
|
|
extrn _max_chain_length : dword
|
|
extrn _prev : word
|
|
extrn _window : byte
|
|
_BSS ends
|
|
|
|
_TEXT segment
|
|
public _match_init
|
|
public _longest_match
|
|
|
|
ifndef WSIZE
|
|
WSIZE equ 32768 ; keep in sync with zip.h !
|
|
endif
|
|
MIN_MATCH equ 3
|
|
MAX_MATCH equ 258
|
|
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
|
|
MAX_DIST equ (WSIZE-MIN_LOOKAHEAD)
|
|
|
|
; initialize or check the variables used in match.asm.
|
|
|
|
_match_init proc near
|
|
ret
|
|
_match_init endp
|
|
|
|
; -----------------------------------------------------------------------
|
|
; Set match_start to the longest match starting at the given string and
|
|
; return its length. Matches shorter or equal to prev_length are discarded,
|
|
; in which case the result is equal to prev_length and match_start is
|
|
; garbage.
|
|
; IN assertions: cur_match is the head of the hash chain for the current
|
|
; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
|
|
|
|
; int longest_match(cur_match)
|
|
|
|
_longest_match proc near
|
|
|
|
cur_match equ dword ptr [esp+20]
|
|
; return address ; esp+16
|
|
push ebp ; esp+12
|
|
push edi ; esp+8
|
|
push esi ; esp+4
|
|
push ebx ; esp
|
|
|
|
; match equ esi
|
|
; scan equ edi
|
|
; chain_length equ ebp
|
|
; best_len equ ebx
|
|
; limit equ edx
|
|
|
|
mov esi,cur_match
|
|
mov ebp,_max_chain_length ; chain_length = max_chain_length
|
|
mov edi,_strstart
|
|
mov edx,edi
|
|
sub edx,MAX_DIST ; limit = strstart-MAX_DIST
|
|
jae short limit_ok
|
|
sub edx,edx ; limit = NIL
|
|
limit_ok:
|
|
add edi,2+offset _window ; edi = offset(window + strstart + 2)
|
|
mov ebx,_prev_length ; best_len = prev_length
|
|
mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
|
|
mov cx,[edi-2] ; cx = scan[0..1]
|
|
cmp ebx,_good_match ; do we have a good match already?
|
|
jb do_scan
|
|
shr ebp,2 ; chain_length >>= 2
|
|
jmp short do_scan
|
|
|
|
align 4 ; align destination of branch
|
|
long_loop:
|
|
; at this point, edi == scan+2, esi == cur_match
|
|
mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
|
|
mov cx,[edi-2] ; cx = scan[0..1]
|
|
short_loop:
|
|
dec ebp ; --chain_length
|
|
jz the_end
|
|
; at this point, edi == scan+2, esi == cur_match,
|
|
; ax = scan[best_len-1..best_len] and cx = scan[0..1]
|
|
and esi,WSIZE-1
|
|
mov si,_prev[esi+esi] ; cur_match = prev[cur_match]
|
|
; top word of esi is still 0
|
|
cmp esi,edx ; cur_match <= limit ?
|
|
jbe short the_end
|
|
do_scan:
|
|
cmp ax,word ptr _window[ebx+esi-1] ; check match at best_len-1
|
|
jne short_loop
|
|
cmp cx,word ptr _window[esi] ; check min_match_length match
|
|
jne short_loop
|
|
|
|
lea esi,_window[esi+2] ; si = match
|
|
mov eax,edi ; ax = scan+2
|
|
mov ecx,(MAX_MATCH-2)/2 ; scan for at most MAX_MATCH bytes
|
|
repe cmpsw ; loop until mismatch
|
|
je maxmatch ; match of length MAX_MATCH?
|
|
mismatch:
|
|
mov cl,[edi-2] ; mismatch on first or second byte?
|
|
sub cl,[esi-2] ; cl = 0 if first bytes equal
|
|
xchg eax,edi ; edi = scan+2, eax = end of scan
|
|
sub eax,edi ; eax = len
|
|
sub esi,eax ; esi = cur_match + 2 + offset(window)
|
|
sub esi,2+offset _window ; esi = cur_match
|
|
sub cl,1 ; set carry if cl == 0 (can't use DEC)
|
|
adc eax,0 ; eax = carry ? len+1 : len
|
|
cmp eax,ebx ; len > best_len ?
|
|
jle long_loop
|
|
mov _match_start,esi ; match_start = cur_match
|
|
mov ebx,eax ; ebx = best_len = len
|
|
cmp eax,MAX_MATCH ; len >= MAX_MATCH ?
|
|
jl long_loop
|
|
the_end:
|
|
mov eax,ebx ; result = eax = best_len
|
|
pop ebx
|
|
pop esi
|
|
pop edi
|
|
pop ebp
|
|
ret
|
|
maxmatch: ; come here if maximum match
|
|
cmpsb ; increment esi and edi
|
|
jmp mismatch ; force match_length = MAX_LENGTH
|
|
|
|
_longest_match endp
|
|
|
|
_TEXT ends
|
|
end
|