|
|
1.1 root 1: /
2: / Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
3: / Kai Uwe Rommel and Igor Mandrichenko.
4: / Permission is granted to any individual or institution to use, copy, or
5: / redistribute this software so long as all of the original files are included
6: / unmodified, that it is not sold for profit, and that this copyright notice
7: / is retained.
8: /
9: / match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.
10:
11: / match.s, optimized version of longest_match() in deflate.c
12: / This version is for 386 Unix or OS/2 in 32 bit mode.
13: / Warning: it uses the AT&T syntax: mov source,dest
14: / This file is only optional. If you want to force the C version,
15: / add -DNO_ASM to CFLAGS in makefile and remove match.o from OBJI).
16: / If you have reduced WSIZE in zip.h, then change its value below.
17: / This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
18:
19: .file "match.s"
20:
21: #if defined(__GO32__) && defined(unix)
22: # undef unix
23: #endif
24:
25: #ifdef unix
26: # define _prev prev
27: # define _window window
28: # define _match_start match_start
29: # define _prev_length prev_length
30: # define _good_match good_match
31: # define _strstart strstart
32: # define _max_chain_length max_chain_length
33:
34: # define _match_init match_init
35: # define _longest_match longest_match
36: #endif
37:
38: #define MAX_MATCH 258
39: #define MAX_MATCH2 128 /* MAX_MATCH/2-1 */
40: #define MIN_MATCH 3
41: #define WSIZE 32768
42: #define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1
43:
44: .globl _match_init
45: .globl _longest_match
46:
47: .text
48:
49: _match_init:
50: ret
51:
52: / -----------------------------------------------------------------------
53: / Set match_start to the longest match starting at the given string and
54: / return its length. Matches shorter or equal to prev_length are discarded,
55: / in which case the result is equal to prev_length and match_start is
56: / garbage.
57: / IN assertions: cur_match is the head of the hash chain for the current
58: / string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
59:
60: _longest_match: /* int longest_match(cur_match) */
61:
62: #define cur_match 20(%esp)
63: / return address / esp+16
64: push %ebp / esp+12
65: push %edi / esp+8
66: push %esi / esp+4
67: push %ebx / esp
68:
69: / match equ esi
70: / scan equ edi
71: / chain_length equ ebp
72: / best_len equ ebx
73: / limit equ edx
74:
75: mov cur_match,%esi
76: mov _max_chain_length,%ebp / chain_length = max_chain_length
77: mov _strstart,%edi
78: mov %edi,%edx
79: sub $ MAX_DIST,%edx / limit = strstart-MAX_DIST
80: jae limit_ok
81: sub %edx,%edx / limit = NIL
82: limit_ok:
83: add $_window+2,%edi / edi = offset(window + strstart + 2)
84: mov _prev_length,%ebx / best_len = prev_length
85: movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
86: movw -2(%edi),%cx / cx = scan[0..1]
87: cmp _good_match,%ebx / do we have a good match already?
88: jb do_scan
89: shr $2,%ebp / chain_length >>= 2
90: jmp do_scan
91:
92: .align 4
93: long_loop:
94: / at this point, edi == scan+2, esi == cur_match
95: movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
96: movw -2(%edi),%cx / cx = scan[0..1]
97: short_loop:
98: dec %ebp / --chain_length
99: jz the_end
100: / at this point, di == scan+2, si == cur_match,
101: / ax = scan[best_len-1..best_len] and cx = scan[0..1]
102: and $ WSIZE-1, %esi
103: movw _prev(%esi,%esi),%si / cur_match = prev[cur_match]
104: / top word of esi is still 0
105: cmp %edx,%esi / cur_match <= limit ?
106: jbe the_end
107: do_scan:
108: cmpw _window-1(%ebx,%esi),%ax /check match at best_len-1
109: jne short_loop
110: cmpw _window(%esi),%cx / check min_match_length match
111: jne short_loop
112:
113: lea _window+2(%esi),%esi / si = match
114: mov %edi,%eax / ax = scan+2
115: mov $ MAX_MATCH2,%ecx / scan for at most MAX_MATCH bytes
116: #ifdef unix
117: repz; cmpsw / loop until mismatch
118: #else
119: repe; cmpsw
120: #endif
121: je maxmatch / match of length MAX_MATCH?
122: mismatch:
123: movb -2(%edi),%cl / mismatch on first or second byte?
124: subb -2(%esi),%cl / cl = 0 if first bytes equal
125: xchg %edi,%eax / edi = scan+2, eax = end of scan
126: sub %edi,%eax / eax = len
127: sub %eax,%esi / esi = cur_match + 2 + offset(window)
128: sub $_window+2,%esi / esi = cur_match
129: subb $1,%cl / set carry if cl == 0 (cannot use DEC)
130: adc $0,%eax / eax = carry ? len+1 : len
131: cmp %ebx,%eax / len > best_len ?
132: jle long_loop
133: mov %esi,_match_start / match_start = cur_match
134: mov %eax,%ebx / ebx = best_len = len
135: cmp $ MAX_MATCH,%eax / len >= MAX_MATCH ?
136: jl long_loop
137: the_end:
138: mov %ebx,%eax / result = eax = best_len
139: pop %ebx
140: pop %esi
141: pop %edi
142: pop %ebp
143: ret
144: maxmatch:
145: cmpsb
146: jmp mismatch
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.