]> git.cworth.org Git - gzip/blob - msdos/match.asm
Imported Upstream version 1.3.2
[gzip] / msdos / match.asm
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
25 ifndef DYN_ALLOC
26         extrn   _prev         : word
27         extrn   _window       : byte
28         prev    equ  _prev    ; offset part
29         window  equ  _window
30 endif
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
39 ifdef 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
46 else
47         wseg    dw seg _window
48         window_seg equ wseg
49         window_off equ offset _window
50 endif
51 _DATA    ends
52
53 DGROUP  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
67 prev_ptr    dw  seg _prev               ; pointer to the prev array
68 ifdef 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
71 endif
72
73 ; initialize or check the variables used in match.asm.
74
75 ifdef __LARGE__
76 _match_init proc far                    ; 'proc far' for large model
77 else
78 _match_init proc near                   ; 'proc near' for compact model
79 endif
80 ifdef 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
85 else
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
93 endif
94 ifdef 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
106 else
107         prev_seg  equ cs:prev_ptr
108 endif
109         ret
110 ifdef __LARGE__
111         extrn   _exit : far             ; 'far' for large model
112 else
113         extrn   _exit : near            ; 'near' for compact model
114 endif
115 error:  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
129 ifdef __LARGE__
130 _longest_match  proc far                 ; 'proc far' for large model
131 else
132 _longest_match  proc near                ; 'proc near' for compact model
133 endif
134         push    bp
135         mov     bp,sp
136         push    di
137         push    si
138         push    ds
139
140 ifdef __LARGE__
141         cur_match    equ word ptr [bp+6] ; [bp+6] for large model
142 else
143         cur_match    equ word ptr [bp+4] ; [bp+4] for compact model
144 endif
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
161 limit_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
176 long_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
181 short_loop:
182 ; at this point, di == scan+2, si = cur_match,
183 ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
184 if (WSIZE-32768)
185         and     si,WSIZE-1              ; not needed if WSIZE=32768
186 endif
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
193 do_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?
206 mismatch:
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
221 the_end:
222         pop     ds
223         assume  ds: DGROUP
224 ifdef SS_NEQ_DS
225         mov     ax,ma_start             ; garbage if no match found
226         mov     ds:_match_start,ax
227 endif
228         pop     si
229         pop     di
230         pop     bp
231         mov     ax,bx                   ; result = ax = best_len
232         ret
233 maxmatch:                               ; 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
240 end