Initial revision
[silc.git] / lib / zlib / contrib / asm386 / gvmat32c.c
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 */