source: trunk/essentials/app-arch/gzip/msdos/match.asm

Last change on this file was 3325, checked in by bird, 18 years ago

gzip 1.3.11

File size: 8.1 KB
Line 
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.
5;
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
11; below.
12;
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;
16;
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.
20
21; $Id: match.asm,v 0.6 1993/01/21 18:49:05 jloup Exp $
22
23 name match
24
25ifndef DYN_ALLOC
26 extrn _prev : word
27 extrn _window : byte
28 prev equ _prev ; offset part
29 window equ _window
30endif
31
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
39ifdef DYN_ALLOC
40 extrn _prev : word
41 extrn _window : word
42 prev equ 0 ; offset forced to zero
43 window equ 0
44 window_seg equ _window[2]
45 window_off equ 0
46else
47 wseg dw seg _window
48 window_seg equ wseg
49 window_off equ offset _window
50endif
51_DATA ends
52
53DGROUP group _DATA
54
55_TEXT segment word public 'CODE'
56 assume cs: _TEXT, ds: DGROUP
57
58 public _match_init
59 public _longest_match
60
61 MIN_MATCH equ 3
62 MAX_MATCH equ 258
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)
66
67prev_ptr dw seg _prev ; pointer to the prev array
68ifdef SS_NEQ_DS
69 match_start dw 0 ; copy of _match_start if SS != DS
70 nice_match dw 0 ; copy of _nice_match if SS != DS
71endif
72
73; initialize or check the variables used in match.asm.
74
75ifdef __LARGE__
76_match_init proc far ; 'proc far' for large model
77else
78_match_init proc near ; 'proc near' for compact model
79endif
80ifdef SS_NEQ_DS
81 ma_start equ cs:match_start ; does not work on OS/2
82 nice equ cs:nice_match
83 mov ax,_nice_match
84 mov cs:nice_match,ax ; ugly write to code, crash on OS/2
85else
86 assume ss: DGROUP
87 ma_start equ ss:_match_start
88 nice equ ss:_nice_match
89 mov ax,ds
90 mov bx,ss
91 cmp ax,bx ; SS == DS?
92 jne error
93endif
94ifdef DYN_ALLOC
95 cmp _prev[0],0 ; verify zero offset
96 jne error
97 cmp _window[0],0
98 jne error
99 ifdef SS_NEQ_DS
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
103 else
104 prev_seg equ ss:_prev[2] ; works on OS/2 if SS == DS
105 endif
106else
107 prev_seg equ cs:prev_ptr
108endif
109 ret
110ifdef __LARGE__
111 extrn _exit : far ; 'far' for large model
112else
113 extrn _exit : near ; 'near' for compact model
114endif
115error: call _exit
116
117_match_init endp
118
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
123; garbage.
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
126
127; int longest_match(cur_match)
128
129ifdef __LARGE__
130_longest_match proc far ; 'proc far' for large model
131else
132_longest_match proc near ; 'proc near' for compact model
133endif
134 push bp
135 mov bp,sp
136 push di
137 push si
138 push ds
139
140ifdef __LARGE__
141 cur_match equ word ptr [bp+6] ; [bp+6] for large model
142else
143 cur_match equ word ptr [bp+4] ; [bp+4] for compact model
144endif
145
146; window equ es:window (es:0 for DYN_ALLOC)
147; prev equ ds:prev
148; match equ es:si
149; scan equ es:di
150; chain_length equ bp
151; best_len equ bx
152; limit equ dx
153
154 mov si,cur_match ; use bp before it is destroyed
155 mov bp,_max_chain_length ; chain_length = max_chain_length
156 mov di,_strstart
157 mov dx,di
158 sub dx,MAX_DIST ; limit = strstart-MAX_DIST
159 jae limit_ok
160 sub dx,dx ; limit = NIL
161limit_ok:
162 add di,2+window_off ; di = offset(window + strstart + 2)
163 mov bx,_prev_length ; best_len = prev_length
164 mov es,window_seg
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)
169 assume ds: nothing
170 jb do_scan ; good match?
171 shr bp,1 ; chain_length >>= 2
172 shr bp,1
173 jmp short do_scan
174
175 even ; align destination of branch
176long_loop:
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
181short_loop:
182; at this point, di == scan+2, si = cur_match,
183; ax = scan[best_len-1..best_len] and cx = scan[0..1]
184if (WSIZE-32768)
185 and si,WSIZE-1 ; not needed if WSIZE=32768
186endif
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 ?
190 jbe the_end
191 dec bp ; --chain_length
192 jz the_end
193do_scan:
194 cmp ax,word ptr es:window[bx+si-1] ; check match at best_len-1
195 jne short_loop
196 cmp cx,word ptr es:window[si] ; check min_match_length match
197 jne short_loop
198
199 lea si,window[si+2] ; si = match
200 mov ax,di ; ax = scan+2
201 mov cx,es
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?
206mismatch:
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
210 sub ax,di ; ax = len
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 ?
216 jle long_loop
217 mov ma_start,si ; match_start = cur_match
218 mov bx,ax ; bx = best_len = len
219 cmp ax,nice ; len >= nice_match ?
220 jl long_loop
221the_end:
222 pop ds
223 assume ds: DGROUP
224ifdef SS_NEQ_DS
225 mov ax,ma_start ; garbage if no match found
226 mov ds:_match_start,ax
227endif
228 pop si
229 pop di
230 pop bp
231 mov ax,bx ; result = ax = best_len
232 ret
233maxmatch: ; come here if maximum match
234 cmpsb ; increment si and di
235 jmp mismatch ; force match_length = MAX_LENGTH
236
237_longest_match endp
238
239_TEXT ends
240end
Note: See TracBrowser for help on using the repository browser.