diff options
Diffstat (limited to 'contrib/asm386/gvmat32c.c')
-rw-r--r-- | contrib/asm386/gvmat32c.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/contrib/asm386/gvmat32c.c b/contrib/asm386/gvmat32c.c new file mode 100644 index 0000000..43d530b --- /dev/null +++ b/contrib/asm386/gvmat32c.c | |||
@@ -0,0 +1,229 @@ | |||
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 | //#pragma optimize("agt",on) | ||
11 | |||
12 | #include "deflate.h" | ||
13 | |||
14 | #undef FAR | ||
15 | #include <windows.h> | ||
16 | |||
17 | #ifdef ASMV | ||
18 | |||
19 | #define NIL 0 | ||
20 | |||
21 | static unsigned int tot=0; | ||
22 | static unsigned int totl0=0; | ||
23 | static unsigned int totl0p0=0; | ||
24 | static unsigned int ba0=0; | ||
25 | static unsigned int ba1=0; | ||
26 | static unsigned int cpta=0; | ||
27 | static unsigned int cptb=0; | ||
28 | |||
29 | #define UNALIGNED_OK | ||
30 | #define gvshow(a,b,c,d) | ||
31 | /* | ||
32 | void gvshow(int chain_length,int len,int limit,ushf* prev) | ||
33 | { | ||
34 | static int ival=0; | ||
35 | char sz[80]; | ||
36 | unsigned long i; | ||
37 | int prev0=*prev; | ||
38 | ival++; | ||
39 | //wsprintf(sz,"call %u, len=%u, chain_length=%u\n",ival,len,chain_length); | ||
40 | //OutputDebugString(sz); | ||
41 | tot++; | ||
42 | if (limit==NIL) | ||
43 | totl0++; | ||
44 | if ((limit==NIL) && (prev0==0)) | ||
45 | totl0p0++; | ||
46 | for (i=limit+1;i<32768;i++) | ||
47 | { | ||
48 | ush va=*(prev+i); | ||
49 | if (ba0>4000000000) | ||
50 | { | ||
51 | ba0+=10; | ||
52 | } | ||
53 | ba0++; | ||
54 | if ((va>limit) || (va==0)) | ||
55 | continue; | ||
56 | ba1++; | ||
57 | } | ||
58 | } | ||
59 | */ | ||
60 | |||
61 | |||
62 | /* if your C compiler don't add underline before function name, | ||
63 | define ADD_UNDERLINE_ASMFUNC */ | ||
64 | #ifdef ADD_UNDERLINE_ASMFUNC | ||
65 | #define longest_match_asm7fff _longest_match_asm7fff | ||
66 | #endif | ||
67 | void match_init() | ||
68 | { | ||
69 | } | ||
70 | |||
71 | uInt longest_match_c( | ||
72 | deflate_state *s, | ||
73 | IPos cur_match); /* current match */ | ||
74 | |||
75 | |||
76 | uInt longest_match_asm7fff( | ||
77 | deflate_state *s, | ||
78 | IPos cur_match); /* current match */ | ||
79 | |||
80 | uInt longest_match( | ||
81 | deflate_state *s, | ||
82 | IPos cur_match) /* current match */ | ||
83 | { | ||
84 | if (s->w_mask == 0x7fff) | ||
85 | return longest_match_asm7fff(s,cur_match); | ||
86 | return longest_match_c(s,cur_match); | ||
87 | } | ||
88 | |||
89 | |||
90 | |||
91 | uInt longest_match_c(s, cur_match) | ||
92 | deflate_state *s; | ||
93 | IPos cur_match; /* current match */ | ||
94 | { | ||
95 | unsigned chain_length = s->max_chain_length;/* max hash chain length */ | ||
96 | register Bytef *scan = s->window + s->strstart; /* current string */ | ||
97 | register Bytef *match; /* matched string */ | ||
98 | register int len; /* length of current match */ | ||
99 | int best_len = s->prev_length; /* best match length so far */ | ||
100 | int nice_match = s->nice_match; /* stop if match long enough */ | ||
101 | IPos limit = s->strstart > (IPos)MAX_DIST(s) ? | ||
102 | s->strstart - (IPos)MAX_DIST(s) : NIL; | ||
103 | /* Stop when cur_match becomes <= limit. To simplify the code, | ||
104 | * we prevent matches with the string of window index 0. | ||
105 | */ | ||
106 | Posf *prev = s->prev; | ||
107 | uInt wmask = s->w_mask; | ||
108 | |||
109 | #ifdef UNALIGNED_OK | ||
110 | /* Compare two bytes at a time. Note: this is not always beneficial. | ||
111 | * Try with and without -DUNALIGNED_OK to check. | ||
112 | */ | ||
113 | register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; | ||
114 | register ush scan_start = *(ushf*)scan; | ||
115 | register ush scan_end = *(ushf*)(scan+best_len-1); | ||
116 | #else | ||
117 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | ||
118 | register Byte scan_end1 = scan[best_len-1]; | ||
119 | register Byte scan_end = scan[best_len]; | ||
120 | #endif | ||
121 | |||
122 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | ||
123 | * It is easy to get rid of this optimization if necessary. | ||
124 | */ | ||
125 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | ||
126 | |||
127 | /* Do not waste too much time if we already have a good match: */ | ||
128 | if (s->prev_length >= s->good_match) { | ||
129 | chain_length >>= 2; | ||
130 | } | ||
131 | /* Do not look for matches beyond the end of the input. This is necessary | ||
132 | * to make deflate deterministic. | ||
133 | */ | ||
134 | if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; | ||
135 | |||
136 | Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); | ||
137 | |||
138 | do { | ||
139 | Assert(cur_match < s->strstart, "no future"); | ||
140 | match = s->window + cur_match; | ||
141 | |||
142 | /* Skip to next match if the match length cannot increase | ||
143 | * or if the match length is less than 2: | ||
144 | */ | ||
145 | #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) | ||
146 | /* This code assumes sizeof(unsigned short) == 2. Do not use | ||
147 | * UNALIGNED_OK if your compiler uses a different size. | ||
148 | */ | ||
149 | if (*(ushf*)(match+best_len-1) != scan_end || | ||
150 | *(ushf*)match != scan_start) continue; | ||
151 | |||
152 | /* It is not necessary to compare scan[2] and match[2] since they are | ||
153 | * always equal when the other bytes match, given that the hash keys | ||
154 | * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at | ||
155 | * strstart+3, +5, ... up to strstart+257. We check for insufficient | ||
156 | * lookahead only every 4th comparison; the 128th check will be made | ||
157 | * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is | ||
158 | * necessary to put more guard bytes at the end of the window, or | ||
159 | * to check more often for insufficient lookahead. | ||
160 | */ | ||
161 | Assert(scan[2] == match[2], "scan[2]?"); | ||
162 | scan++, match++; | ||
163 | do { | ||
164 | } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && | ||
165 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | ||
166 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | ||
167 | *(ushf*)(scan+=2) == *(ushf*)(match+=2) && | ||
168 | scan < strend); | ||
169 | /* The funny "do {}" generates better code on most compilers */ | ||
170 | |||
171 | /* Here, scan <= window+strstart+257 */ | ||
172 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | ||
173 | if (*scan == *match) scan++; | ||
174 | |||
175 | len = (MAX_MATCH - 1) - (int)(strend-scan); | ||
176 | scan = strend - (MAX_MATCH-1); | ||
177 | |||
178 | #else /* UNALIGNED_OK */ | ||
179 | |||
180 | if (match[best_len] != scan_end || | ||
181 | match[best_len-1] != scan_end1 || | ||
182 | *match != *scan || | ||
183 | *++match != scan[1]) continue; | ||
184 | |||
185 | /* The check at best_len-1 can be removed because it will be made | ||
186 | * again later. (This heuristic is not always a win.) | ||
187 | * It is not necessary to compare scan[2] and match[2] since they | ||
188 | * are always equal when the other bytes match, given that | ||
189 | * the hash keys are equal and that HASH_BITS >= 8. | ||
190 | */ | ||
191 | scan += 2, match++; | ||
192 | Assert(*scan == *match, "match[2]?"); | ||
193 | |||
194 | /* We check for insufficient lookahead only every 8th comparison; | ||
195 | * the 256th check will be made at strstart+258. | ||
196 | */ | ||
197 | do { | ||
198 | } while (*++scan == *++match && *++scan == *++match && | ||
199 | *++scan == *++match && *++scan == *++match && | ||
200 | *++scan == *++match && *++scan == *++match && | ||
201 | *++scan == *++match && *++scan == *++match && | ||
202 | scan < strend); | ||
203 | |||
204 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | ||
205 | |||
206 | len = MAX_MATCH - (int)(strend - scan); | ||
207 | scan = strend - MAX_MATCH; | ||
208 | |||
209 | #endif /* UNALIGNED_OK */ | ||
210 | |||
211 | if (len > best_len) { | ||
212 | s->match_start = cur_match; | ||
213 | best_len = len; | ||
214 | if (len >= nice_match) break; | ||
215 | #ifdef UNALIGNED_OK | ||
216 | scan_end = *(ushf*)(scan+best_len-1); | ||
217 | #else | ||
218 | scan_end1 = scan[best_len-1]; | ||
219 | scan_end = scan[best_len]; | ||
220 | #endif | ||
221 | } | ||
222 | } while ((cur_match = prev[cur_match & wmask]) > limit | ||
223 | && --chain_length != 0); | ||
224 | |||
225 | if ((uInt)best_len <= s->lookahead) return best_len; | ||
226 | return s->lookahead; | ||
227 | } | ||
228 | |||
229 | #endif /* ASMV */ | ||