]>
Commit | Line | Data |
---|---|---|
b919490c NC |
1 | /* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 |
2 | * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. | |
3 | * File written by Gilles Vollant, by modifiying the longest_match | |
4 | * from Jean-loup Gailly in deflate.c | |
5 | * it prepare all parameters and call the assembly longest_match_gvasm | |
6 | * longest_match execute standard C code is wmask != 0x7fff | |
7 | * (assembly code is faster with a fixed wmask) | |
8 | * | |
9 | */ | |
10 | ||
11 | #include "deflate.h" | |
12 | ||
13 | #undef FAR | |
14 | #include <windows.h> | |
15 | ||
16 | #ifdef ASMV | |
17 | #define NIL 0 | |
18 | ||
19 | #define UNALIGNED_OK | |
20 | ||
21 | ||
22 | /* if your C compiler don't add underline before function name, | |
23 | define ADD_UNDERLINE_ASMFUNC */ | |
24 | #ifdef ADD_UNDERLINE_ASMFUNC | |
25 | #define longest_match_7fff _longest_match_7fff | |
26 | #endif | |
27 | ||
28 | ||
29 | ||
30 | void match_init() | |
31 | { | |
32 | } | |
33 | ||
34 | unsigned long cpudetect32(); | |
35 | ||
36 | uInt longest_match_c( | |
37 | deflate_state *s, | |
38 | IPos cur_match); /* current match */ | |
39 | ||
40 | ||
41 | uInt longest_match_7fff( | |
42 | deflate_state *s, | |
43 | IPos cur_match); /* current match */ | |
44 | ||
45 | uInt longest_match( | |
46 | deflate_state *s, | |
47 | IPos cur_match) /* current match */ | |
48 | { | |
49 | static uInt iIsPPro=2; | |
50 | ||
51 | if ((s->w_mask == 0x7fff) && (iIsPPro==0)) | |
52 | return longest_match_7fff(s,cur_match); | |
53 | ||
54 | if (iIsPPro==2) | |
55 | iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; | |
56 | ||
57 | return longest_match_c(s,cur_match); | |
58 | } | |
59 | ||
60 | ||
61 | ||
62 | uInt longest_match_c(s, cur_match) | |
63 | deflate_state *s; | |
64 | IPos cur_match; /* current match */ | |
65 | { | |
66 | unsigned chain_length = s->max_chain_length;/* max hash chain length */ | |
67 | register Bytef *scan = s->window + s->strstart; /* current string */ | |
68 | register Bytef *match; /* matched string */ | |
69 | register int len; /* length of current match */ | |
70 | int best_len = s->prev_length; /* best match length so far */ | |
71 | int nice_match = s->nice_match; /* stop if match long enough */ | |
72 | IPos limit = s->strstart > (IPos)MAX_DIST(s) ? | |
73 | s->strstart - (IPos)MAX_DIST(s) : NIL; | |
74 | /* Stop when cur_match becomes <= limit. To simplify the code, | |
75 | * we prevent matches with the string of window index 0. | |
76 | */ | |
77 | Posf *prev = s->prev; | |
78 | uInt wmask = s->w_mask; | |
79 | ||
80 | #ifdef UNALIGNED_OK | |
81 | /* Compare two bytes at a time. Note: this is not always beneficial. | |
82 | * Try with and without -DUNALIGNED_OK to check. | |
83 | */ | |
84 | register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; | |
85 | register ush scan_start = *(ushf*)scan; | |
86 | register ush scan_end = *(ushf*)(scan+best_len-1); | |
87 | #else | |
88 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | |
89 | register Byte scan_end1 = scan[best_len-1]; | |
90 | register Byte scan_end = scan[best_len]; | |
91 | #endif | |
92 | ||
93 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | |
94 | * It is easy to get rid of this optimization if necessary. | |
95 | */ | |
96 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | |
97 | ||
98 | /* Do not waste too much time if we already have a good match: */ | |
99 | if (s->prev_length >= s->good_match) { | |
100 | chain_length >>= 2; | |
101 | } | |
102 | /* Do not look for matches beyond the end of the input. This is necessary | |
103 | * to make deflate deterministic. | |
104 | */ | |
105 | if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; | |
106 | ||
107 | Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); | |
108 | ||
109 | do { | |
110 | Assert(cur_match < s->strstart, "no future"); | |
111 | match = s->window + cur_match; | |
112 | ||
113 | /* Skip to next match if the match length cannot increase | |
114 | * or if the match length is less than 2: | |
115 | */ | |
116 | #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) | |
117 | /* This code assumes sizeof(unsigned short) == 2. Do not use | |
118 | * UNALIGNED_OK if your compiler uses a different size. | |
119 | */ | |
120 | if (*(ushf*)(match+best_len-1) != scan_end || | |
121 | *(ushf*)match != scan_start) continue; | |
122 | ||
123 | /* It is not necessary to compare scan[2] and match[2] since they are | |
124 | * always equal when the other bytes match, given that the hash keys | |
125 | * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at | |
126 | * strstart+3, +5, ... up to strstart+257. We check for insufficient | |
127 | * lookahead only every 4th comparison; the 128th check will be made | |
128 | * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is | |
129 | * necessary to put more guard bytes at the end of the window, or | |
130 | * to check more often for insufficient lookahead. | |
131 | */ | |
132 | Assert(scan[2] == match[2], "scan[2]?"); | |
133 | scan++, match++; | |
134 | do { | |
135 | } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
136 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
137 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
138 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | |
139 | scan < strend); | |
140 | /* The funny "do {}" generates better code on most compilers */ | |
141 | ||
142 | /* Here, scan <= window+strstart+257 */ | |
143 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
144 | if (*scan == *match) scan++; | |
145 | ||
146 | len = (MAX_MATCH - 1) - (int)(strend-scan); | |
147 | scan = strend - (MAX_MATCH-1); | |
148 | ||
149 | #else /* UNALIGNED_OK */ | |
150 | ||
151 | if (match[best_len] != scan_end || | |
152 | match[best_len-1] != scan_end1 || | |
153 | *match != *scan || | |
154 | *++match != scan[1]) continue; | |
155 | ||
156 | /* The check at best_len-1 can be removed because it will be made | |
157 | * again later. (This heuristic is not always a win.) | |
158 | * It is not necessary to compare scan[2] and match[2] since they | |
159 | * are always equal when the other bytes match, given that | |
160 | * the hash keys are equal and that HASH_BITS >= 8. | |
161 | */ | |
162 | scan += 2, match++; | |
163 | Assert(*scan == *match, "match[2]?"); | |
164 | ||
165 | /* We check for insufficient lookahead only every 8th comparison; | |
166 | * the 256th check will be made at strstart+258. | |
167 | */ | |
168 | do { | |
169 | } while (*++scan == *++match && *++scan == *++match && | |
170 | *++scan == *++match && *++scan == *++match && | |
171 | *++scan == *++match && *++scan == *++match && | |
172 | *++scan == *++match && *++scan == *++match && | |
173 | scan < strend); | |
174 | ||
175 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | |
176 | ||
177 | len = MAX_MATCH - (int)(strend - scan); | |
178 | scan = strend - MAX_MATCH; | |
179 | ||
180 | #endif /* UNALIGNED_OK */ | |
181 | ||
182 | if (len > best_len) { | |
183 | s->match_start = cur_match; | |
184 | best_len = len; | |
185 | if (len >= nice_match) break; | |
186 | #ifdef UNALIGNED_OK | |
187 | scan_end = *(ushf*)(scan+best_len-1); | |
188 | #else | |
189 | scan_end1 = scan[best_len-1]; | |
190 | scan_end = scan[best_len]; | |
191 | #endif | |
192 | } | |
193 | } while ((cur_match = prev[cur_match & wmask]) > limit | |
194 | && --chain_length != 0); | |
195 | ||
196 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; | |
197 | return s->lookahead; | |
198 | } | |
199 | ||
200 | #endif /* ASMV */ |