VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.1/contrib/masm686/match.asm@ 30344

Last change on this file since 30344 was 6392, checked in by vboxsync, 17 years ago

export libpng and zlib so Windows and OS/2 builds cleanly.

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1
2; match.asm -- Pentium-Pro optimized version of longest_match()
3;
4; Updated for zlib 1.1.3 and converted to MASM 6.1x
5; Copyright (C) 2000 Dan Higdon <[email protected]>
6; and Chuck Walbourn <[email protected]>
7; Corrections by Cosmin Truta <[email protected]>
8;
9; This is free software; you can redistribute it and/or modify it
10; under the terms of the GNU General Public License.
11
12; Based on match.S
13; Written for zlib 1.1.2
14; Copyright (C) 1998 Brian Raiter <[email protected]>
15
16 .686P
17 .MODEL FLAT
18
19;===========================================================================
20; EQUATES
21;===========================================================================
22
23MAX_MATCH EQU 258
24MIN_MATCH EQU 3
25MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)
26MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7))
27
28;===========================================================================
29; STRUCTURES
30;===========================================================================
31
32; This STRUCT assumes a 4-byte alignment
33
34DEFLATE_STATE STRUCT
35ds_strm dd ?
36ds_status dd ?
37ds_pending_buf dd ?
38ds_pending_buf_size dd ?
39ds_pending_out dd ?
40ds_pending dd ?
41ds_wrap dd ?
42ds_data_type db ?
43ds_method db ?
44 db ? ; padding
45 db ? ; padding
46ds_last_flush dd ?
47ds_w_size dd ? ; used
48ds_w_bits dd ?
49ds_w_mask dd ? ; used
50ds_window dd ? ; used
51ds_window_size dd ?
52ds_prev dd ? ; used
53ds_head dd ?
54ds_ins_h dd ?
55ds_hash_size dd ?
56ds_hash_bits dd ?
57ds_hash_mask dd ?
58ds_hash_shift dd ?
59ds_block_start dd ?
60ds_match_length dd ? ; used
61ds_prev_match dd ? ; used
62ds_match_available dd ?
63ds_strstart dd ? ; used
64ds_match_start dd ? ; used
65ds_lookahead dd ? ; used
66ds_prev_length dd ? ; used
67ds_max_chain_length dd ? ; used
68ds_max_laxy_match dd ?
69ds_level dd ?
70ds_strategy dd ?
71ds_good_match dd ? ; used
72ds_nice_match dd ? ; used
73
74; Don't need anymore of the struct for match
75DEFLATE_STATE ENDS
76
77;===========================================================================
78; CODE
79;===========================================================================
80_TEXT SEGMENT
81
82;---------------------------------------------------------------------------
83; match_init
84;---------------------------------------------------------------------------
85 ALIGN 4
86PUBLIC _match_init
87_match_init PROC
88 ; no initialization needed
89 ret
90_match_init ENDP
91
92;---------------------------------------------------------------------------
93; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
94;---------------------------------------------------------------------------
95 ALIGN 4
96
97PUBLIC _longest_match
98_longest_match PROC
99
100; Since this code uses EBP for a scratch register, the stack frame must
101; be manually constructed and referenced relative to the ESP register.
102
103; Stack image
104; Variables
105chainlenwmask = 0 ; high word: current chain len
106 ; low word: s->wmask
107window = 4 ; local copy of s->window
108windowbestlen = 8 ; s->window + bestlen
109scanend = 12 ; last two bytes of string
110scanstart = 16 ; first two bytes of string
111scanalign = 20 ; dword-misalignment of string
112nicematch = 24 ; a good enough match size
113bestlen = 28 ; size of best match so far
114scan = 32 ; ptr to string wanting match
115varsize = 36 ; number of bytes (also offset to last saved register)
116
117; Saved Registers (actually pushed into place)
118ebx_save = 36
119edi_save = 40
120esi_save = 44
121ebp_save = 48
122
123; Parameters
124retaddr = 52
125deflatestate = 56
126curmatch = 60
127
128; Save registers that the compiler may be using
129 push ebp
130 push edi
131 push esi
132 push ebx
133
134; Allocate local variable space
135 sub esp,varsize
136
137; Retrieve the function arguments. ecx will hold cur_match
138; throughout the entire function. edx will hold the pointer to the
139; deflate_state structure during the function's setup (before
140; entering the main loop).
141
142 mov edx, [esp+deflatestate]
143ASSUME edx:PTR DEFLATE_STATE
144
145 mov ecx, [esp+curmatch]
146
147; uInt wmask = s->w_mask;
148; unsigned chain_length = s->max_chain_length;
149; if (s->prev_length >= s->good_match) {
150; chain_length >>= 2;
151; }
152
153 mov eax, [edx].ds_prev_length
154 mov ebx, [edx].ds_good_match
155 cmp eax, ebx
156 mov eax, [edx].ds_w_mask
157 mov ebx, [edx].ds_max_chain_length
158 jl SHORT LastMatchGood
159 shr ebx, 2
160LastMatchGood:
161
162; chainlen is decremented once beforehand so that the function can
163; use the sign flag instead of the zero flag for the exit test.
164; It is then shifted into the high word, to make room for the wmask
165; value, which it will always accompany.
166
167 dec ebx
168 shl ebx, 16
169 or ebx, eax
170 mov [esp+chainlenwmask], ebx
171
172; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
173
174 mov eax, [edx].ds_nice_match
175 mov ebx, [edx].ds_lookahead
176 cmp ebx, eax
177 jl SHORT LookaheadLess
178 mov ebx, eax
179LookaheadLess:
180 mov [esp+nicematch], ebx
181
182;/* register Bytef *scan = s->window + s->strstart; */
183
184 mov esi, [edx].ds_window
185 mov [esp+window], esi
186 mov ebp, [edx].ds_strstart
187 lea edi, [esi+ebp]
188 mov [esp+scan],edi
189
190;/* Determine how many bytes the scan ptr is off from being */
191;/* dword-aligned. */
192
193 mov eax, edi
194 neg eax
195 and eax, 3
196 mov [esp+scanalign], eax
197
198;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
199;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
200
201 mov eax, [edx].ds_w_size
202 sub eax, MIN_LOOKAHEAD
203 sub ebp, eax
204 jg SHORT LimitPositive
205 xor ebp, ebp
206LimitPositive:
207
208;/* int best_len = s->prev_length; */
209
210 mov eax, [edx].ds_prev_length
211 mov [esp+bestlen], eax
212
213;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
214
215 add esi, eax
216 mov [esp+windowbestlen], esi
217
218;/* register ush scan_start = *(ushf*)scan; */
219;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
220;/* Posf *prev = s->prev; */
221
222 movzx ebx, WORD PTR[edi]
223 mov [esp+scanstart], ebx
224 movzx ebx, WORD PTR[eax+edi-1]
225 mov [esp+scanend], ebx
226 mov edi, [edx].ds_prev
227
228;/* Jump into the main loop. */
229
230 mov edx, [esp+chainlenwmask]
231 jmp SHORT LoopEntry
232
233;/* do {
234; * match = s->window + cur_match;
235; * if (*(ushf*)(match+best_len-1) != scan_end ||
236; * *(ushf*)match != scan_start) continue;
237; * [...]
238; * } while ((cur_match = prev[cur_match & wmask]) > limit
239; * && --chain_length != 0);
240; *
241; * Here is the inner loop of the function. The function will spend the
242; * majority of its time in this loop, and majority of that time will
243; * be spent in the first ten instructions.
244; *
245; * Within this loop:
246; * %ebx = scanend
247; * %ecx = curmatch
248; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
249; * %esi = windowbestlen - i.e., (window + bestlen)
250; * %edi = prev
251; * %ebp = limit
252; */
253
254 ALIGN 4
255LookupLoop:
256 and ecx, edx
257 movzx ecx, WORD PTR[edi+ecx*2]
258 cmp ecx, ebp
259 jbe LeaveNow
260 sub edx, 000010000H
261 js LeaveNow
262
263LoopEntry:
264 movzx eax, WORD PTR[esi+ecx-1]
265 cmp eax, ebx
266 jnz SHORT LookupLoop
267
268 mov eax, [esp+window]
269 movzx eax, WORD PTR[eax+ecx]
270 cmp eax, [esp+scanstart]
271 jnz SHORT LookupLoop
272
273;/* Store the current value of chainlen. */
274
275 mov [esp+chainlenwmask], edx
276
277;/* Point %edi to the string under scrutiny, and %esi to the string we */
278;/* are hoping to match it up with. In actuality, %esi and %edi are */
279;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
280;/* initialized to -(MAX_MATCH_8 - scanalign). */
281
282 mov esi, [esp+window]
283 mov edi, [esp+scan]
284 add esi, ecx
285 mov eax, [esp+scanalign]
286 mov edx, -MAX_MATCH_8
287 lea edi, [edi+eax+MAX_MATCH_8]
288 lea esi, [esi+eax+MAX_MATCH_8]
289
290;/* Test the strings for equality, 8 bytes at a time. At the end,
291; * adjust %edx so that it is offset to the exact byte that mismatched.
292; *
293; * We already know at this point that the first three bytes of the
294; * strings match each other, and they can be safely passed over before
295; * starting the compare loop. So what this code does is skip over 0-3
296; * bytes, as much as necessary in order to dword-align the %edi
297; * pointer. (%esi will still be misaligned three times out of four.)
298; *
299; * It should be confessed that this loop usually does not represent
300; * much of the total running time. Replacing it with a more
301; * straightforward "rep cmpsb" would not drastically degrade
302; * performance.
303; */
304
305LoopCmps:
306 mov eax, DWORD PTR[esi+edx]
307 xor eax, DWORD PTR[edi+edx]
308 jnz SHORT LeaveLoopCmps
309
310 mov eax, DWORD PTR[esi+edx+4]
311 xor eax, DWORD PTR[edi+edx+4]
312 jnz SHORT LeaveLoopCmps4
313
314 add edx, 8
315 jnz SHORT LoopCmps
316 jmp LenMaximum
317 ALIGN 4
318
319LeaveLoopCmps4:
320 add edx, 4
321
322LeaveLoopCmps:
323 test eax, 00000FFFFH
324 jnz SHORT LenLower
325
326 add edx, 2
327 shr eax, 16
328
329LenLower:
330 sub al, 1
331 adc edx, 0
332
333;/* Calculate the length of the match. If it is longer than MAX_MATCH, */
334;/* then automatically accept it as the best possible match and leave. */
335
336 lea eax, [edi+edx]
337 mov edi, [esp+scan]
338 sub eax, edi
339 cmp eax, MAX_MATCH
340 jge SHORT LenMaximum
341
342;/* If the length of the match is not longer than the best match we */
343;/* have so far, then forget it and return to the lookup loop. */
344
345 mov edx, [esp+deflatestate]
346 mov ebx, [esp+bestlen]
347 cmp eax, ebx
348 jg SHORT LongerMatch
349 mov esi, [esp+windowbestlen]
350 mov edi, [edx].ds_prev
351 mov ebx, [esp+scanend]
352 mov edx, [esp+chainlenwmask]
353 jmp LookupLoop
354 ALIGN 4
355
356;/* s->match_start = cur_match; */
357;/* best_len = len; */
358;/* if (len >= nice_match) break; */
359;/* scan_end = *(ushf*)(scan+best_len-1); */
360
361LongerMatch:
362 mov ebx, [esp+nicematch]
363 mov [esp+bestlen], eax
364 mov [edx].ds_match_start, ecx
365 cmp eax, ebx
366 jge SHORT LeaveNow
367 mov esi, [esp+window]
368 add esi, eax
369 mov [esp+windowbestlen], esi
370 movzx ebx, WORD PTR[edi+eax-1]
371 mov edi, [edx].ds_prev
372 mov [esp+scanend], ebx
373 mov edx, [esp+chainlenwmask]
374 jmp LookupLoop
375 ALIGN 4
376
377;/* Accept the current string, with the maximum possible length. */
378
379LenMaximum:
380 mov edx, [esp+deflatestate]
381 mov DWORD PTR[esp+bestlen], MAX_MATCH
382 mov [edx].ds_match_start, ecx
383
384;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
385;/* return s->lookahead; */
386
387LeaveNow:
388 mov edx, [esp+deflatestate]
389 mov ebx, [esp+bestlen]
390 mov eax, [edx].ds_lookahead
391 cmp ebx, eax
392 jg SHORT LookaheadRet
393 mov eax, ebx
394LookaheadRet:
395
396; Restore the stack and return from whence we came.
397
398 add esp, varsize
399 pop ebx
400 pop esi
401 pop edi
402 pop ebp
403 ret
404
405_longest_match ENDP
406
407_TEXT ENDS
408END
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette