1 ; match.asm -- optional optimized asm version of longest match in deflate.c
2 ; Copyright (C) 1992-1993 Jean-loup Gailly
3 ; This is free software; you can redistribute it and/or modify it under the
4 ; terms of the GNU General Public License, see the file COPYING.
6 ; Must be assembled with masm -ml. To be used only with C compact model
7 ; or large model. (For large model, assemble with -D__LARGE__).
8 ; This file is only optional. If you don't have masm or tasm, use the
9 ; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj
10 ; from OBJI). If you have reduced WSIZE in zip.h, then change its value
13 ; Turbo C 2.0 does not support static allocation of more than 64K bytes per
14 ; file, and does not have SS == DS. So TC and BC++ users must use:
15 ; tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match;
17 ; To simplify the code, the option -DDYN_ALLOC is supported for OS/2
18 ; only if the arrays are guaranteed to have zero offset (allocated by
19 ; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C.
28 prev
equ _prev
; offset part
32 _DATA
segment word public 'DATA'
33 extrn _nice_match
: word
34 extrn _match_start
: word
35 extrn _prev_length
: word
36 extrn _good_match
: word
37 extrn _strstart
: word
38 extrn _max_chain_length
: word
42 prev
equ 0 ; offset forced to zero
44 window_seg
equ _window
[2]
49 window_off
equ offset _window
55 _TEXT
segment word public 'CODE'
56 assume cs: _TEXT
, ds: DGROUP
63 WSIZE
equ 32768 ; keep in sync with zip.h !
64 MIN_LOOKAHEAD
equ (MAX_MATCH
+MIN_MATCH
+1)
65 MAX_DIST
equ (WSIZE
-MIN_LOOKAHEAD
)
67 prev_ptr
dw seg _prev
; pointer to the prev array
69 match_start
dw 0 ; copy of _match_start if SS != DS
70 nice_match
dw 0 ; copy of _nice_match if SS != DS
73 ; initialize or check the variables used in match.asm.
76 _match_init
proc far ; 'proc far' for large model
78 _match_init
proc near ; 'proc near' for compact model
81 ma_start
equ cs:match_start
; does not work on OS/2
82 nice
equ cs:nice_match
84 mov cs:nice_match
,ax ; ugly write to code, crash on OS/2
87 ma_start
equ ss:_match_start
88 nice
equ ss:_nice_match
95 cmp _prev
[0],0 ; verify zero offset
100 mov ax,_prev
[2] ; segment value
101 mov cs:prev_ptr
,ax ; ugly write to code, crash on OS/2
102 prev_seg
equ cs:prev_ptr
104 prev_seg
equ ss:_prev
[2] ; works on OS/2 if SS == DS
107 prev_seg
equ cs:prev_ptr
111 extrn _exit
: far ; 'far' for large model
113 extrn _exit
: near ; 'near' for compact model
119 ; -----------------------------------------------------------------------
120 ; Set match_start to the longest match starting at the given string and
121 ; return its length. Matches shorter or equal to prev_length are discarded,
122 ; in which case the result is equal to prev_length and match_start is
124 ; IN assertions: cur_match is the head of the hash chain for the current
125 ; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
127 ; int longest_match(cur_match)
130 _longest_match
proc far ; 'proc far' for large model
132 _longest_match
proc near ; 'proc near' for compact model
141 cur_match
equ word ptr [bp+6] ; [bp+6] for large model
143 cur_match
equ word ptr [bp+4] ; [bp+4] for compact model
146 ; window equ es:window (es:0 for DYN_ALLOC)
150 ; chain_length equ bp
154 mov si,cur_match
; use bp before it is destroyed
155 mov bp,_max_chain_length
; chain_length = max_chain_length
158 sub dx,MAX_DIST
; limit = strstart-MAX_DIST
160 sub dx,dx ; limit = NIL
162 add di,2+window_off
; di = offset(window + strstart + 2)
163 mov bx,_prev_length
; best_len = prev_length
165 mov ax,es:[bx+di-3] ; ax = scan[best_len-1..best_len]
166 mov cx,es:[di-2] ; cx = scan[0..1]
167 cmp bx,_good_match
; do we have a good match already?
168 mov ds,prev_seg
; (does not destroy the flags)
170 jb do_scan
; good match?
171 shr bp,1 ; chain_length >>= 2
175 even
; align destination of branch
177 ; at this point, ds:di == scan+2, ds:si == cur_match
178 mov ax,[bx+di-3] ; ax = scan[best_len-1..best_len]
179 mov cx,[di-2] ; cx = scan[0..1]
180 mov ds,prev_seg
; reset ds to address the prev array
182 ; at this point, di == scan+2, si = cur_match,
183 ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
185 and si,WSIZE
-1 ; not needed if WSIZE=32768
187 shl si,1 ; cur_match as word index
188 mov si,prev
[si] ; cur_match = prev[cur_match]
189 cmp si,dx ; cur_match <= limit ?
191 dec bp ; --chain_length
194 cmp ax,word ptr es:window
[bx+si-1] ; check match at best_len-1
196 cmp cx,word ptr es:window
[si] ; check min_match_length match
199 lea si,window
[si+2] ; si = match
200 mov ax,di ; ax = scan+2
202 mov ds,cx ; ds = es = window
203 mov cx,(MAX_MATCH
-2)/2 ; scan for at most MAX_MATCH bytes
204 repe cmpsw ; loop until mismatch
205 je maxmatch
; match of length MAX_MATCH?
207 mov cl,[di-2] ; mismatch on first or second byte?
208 sub cl,[si-2] ; cl = 0 if first bytes equal
209 xchg ax,di ; di = scan+2, ax = end of scan
211 sub si,ax ; si = cur_match + 2 + offset(window)
212 sub si,2+window_off
; si = cur_match
213 sub cl,1 ; set carry if cl == 0 (can't use DEC)
214 adc ax,0 ; ax = carry ? len+1 : len
215 cmp ax,bx ; len > best_len ?
217 mov ma_start
,si ; match_start = cur_match
218 mov bx,ax ; bx = best_len = len
219 cmp ax,nice
; len >= nice_match ?
225 mov ax,ma_start
; garbage if no match found
226 mov ds:_match_start
,ax
231 mov ax,bx ; result = ax = best_len
233 maxmatch: ; come here if maximum match
234 cmpsb ; increment si and di
235 jmp mismatch
; force match_length = MAX_LENGTH