inffast.c revision 1.1 1 1.1 christos /* $NetBSD: inffast.c,v 1.1 2006/01/14 20:10:29 christos Exp $ */
2 1.1 christos
3 1.1 christos /* inffast.c -- fast decoding
4 1.1 christos * Copyright (C) 1995-2004 Mark Adler
5 1.1 christos * For conditions of distribution and use, see copyright notice in zlib.h
6 1.1 christos */
7 1.1 christos
8 1.1 christos #include "zutil.h"
9 1.1 christos #include "inftrees.h"
10 1.1 christos #include "inflate.h"
11 1.1 christos #include "inffast.h"
12 1.1 christos
13 1.1 christos #ifndef ASMINF
14 1.1 christos
15 1.1 christos /* Allow machine dependent optimization for post-increment or pre-increment.
16 1.1 christos Based on testing to date,
17 1.1 christos Pre-increment preferred for:
18 1.1 christos - PowerPC G3 (Adler)
19 1.1 christos - MIPS R5000 (Randers-Pehrson)
20 1.1 christos Post-increment preferred for:
21 1.1 christos - none
22 1.1 christos No measurable difference:
23 1.1 christos - Pentium III (Anderson)
24 1.1 christos - M68060 (Nikl)
25 1.1 christos */
26 1.1 christos #ifdef POSTINC
27 1.1 christos # define OFF 0
28 1.1 christos # define PUP(a) *(a)++
29 1.1 christos #else
30 1.1 christos # define OFF 1
31 1.1 christos # define PUP(a) *++(a)
32 1.1 christos #endif
33 1.1 christos
34 1.1 christos /*
35 1.1 christos Decode literal, length, and distance codes and write out the resulting
36 1.1 christos literal and match bytes until either not enough input or output is
37 1.1 christos available, an end-of-block is encountered, or a data error is encountered.
38 1.1 christos When large enough input and output buffers are supplied to inflate(), for
39 1.1 christos example, a 16K input buffer and a 64K output buffer, more than 95% of the
40 1.1 christos inflate execution time is spent in this routine.
41 1.1 christos
42 1.1 christos Entry assumptions:
43 1.1 christos
44 1.1 christos state->mode == LEN
45 1.1 christos strm->avail_in >= 6
46 1.1 christos strm->avail_out >= 258
47 1.1 christos start >= strm->avail_out
48 1.1 christos state->bits < 8
49 1.1 christos
50 1.1 christos On return, state->mode is one of:
51 1.1 christos
52 1.1 christos LEN -- ran out of enough output space or enough available input
53 1.1 christos TYPE -- reached end of block code, inflate() to interpret next block
54 1.1 christos BAD -- error in block data
55 1.1 christos
56 1.1 christos Notes:
57 1.1 christos
58 1.1 christos - The maximum input bits used by a length/distance pair is 15 bits for the
59 1.1 christos length code, 5 bits for the length extra, 15 bits for the distance code,
60 1.1 christos and 13 bits for the distance extra. This totals 48 bits, or six bytes.
61 1.1 christos Therefore if strm->avail_in >= 6, then there is enough input to avoid
62 1.1 christos checking for available input while decoding.
63 1.1 christos
64 1.1 christos - The maximum bytes that a single length/distance pair can output is 258
65 1.1 christos bytes, which is the maximum length that can be coded. inflate_fast()
66 1.1 christos requires strm->avail_out >= 258 for each loop to avoid checking for
67 1.1 christos output space.
68 1.1 christos */
69 1.1 christos void inflate_fast(strm, start)
70 1.1 christos z_streamp strm;
71 1.1 christos unsigned start; /* inflate()'s starting value for strm->avail_out */
72 1.1 christos {
73 1.1 christos struct inflate_state FAR *state;
74 1.1 christos unsigned char FAR *in; /* local strm->next_in */
75 1.1 christos unsigned char FAR *last; /* while in < last, enough input available */
76 1.1 christos unsigned char FAR *out; /* local strm->next_out */
77 1.1 christos unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
78 1.1 christos unsigned char FAR *end; /* while out < end, enough space available */
79 1.1 christos #ifdef INFLATE_STRICT
80 1.1 christos unsigned dmax; /* maximum distance from zlib header */
81 1.1 christos #endif
82 1.1 christos unsigned wsize; /* window size or zero if not using window */
83 1.1 christos unsigned whave; /* valid bytes in the window */
84 1.1 christos unsigned write; /* window write index */
85 1.1 christos unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
86 1.1 christos unsigned long hold; /* local strm->hold */
87 1.1 christos unsigned bits; /* local strm->bits */
88 1.1 christos code const FAR *lcode; /* local strm->lencode */
89 1.1 christos code const FAR *dcode; /* local strm->distcode */
90 1.1 christos unsigned lmask; /* mask for first level of length codes */
91 1.1 christos unsigned dmask; /* mask for first level of distance codes */
92 1.1 christos code this; /* retrieved table entry */
93 1.1 christos unsigned op; /* code bits, operation, extra bits, or */
94 1.1 christos /* window position, window bytes to copy */
95 1.1 christos unsigned len; /* match length, unused bytes */
96 1.1 christos unsigned dist; /* match distance */
97 1.1 christos unsigned char FAR *from; /* where to copy match from */
98 1.1 christos
99 1.1 christos /* copy state to local variables */
100 1.1 christos state = (struct inflate_state FAR *)strm->state;
101 1.1 christos in = strm->next_in - OFF;
102 1.1 christos last = in + (strm->avail_in - 5);
103 1.1 christos out = strm->next_out - OFF;
104 1.1 christos beg = out - (start - strm->avail_out);
105 1.1 christos end = out + (strm->avail_out - 257);
106 1.1 christos #ifdef INFLATE_STRICT
107 1.1 christos dmax = state->dmax;
108 1.1 christos #endif
109 1.1 christos wsize = state->wsize;
110 1.1 christos whave = state->whave;
111 1.1 christos write = state->write;
112 1.1 christos window = state->window;
113 1.1 christos hold = state->hold;
114 1.1 christos bits = state->bits;
115 1.1 christos lcode = state->lencode;
116 1.1 christos dcode = state->distcode;
117 1.1 christos lmask = (1U << state->lenbits) - 1;
118 1.1 christos dmask = (1U << state->distbits) - 1;
119 1.1 christos
120 1.1 christos /* decode literals and length/distances until end-of-block or not enough
121 1.1 christos input data or output space */
122 1.1 christos do {
123 1.1 christos if (bits < 15) {
124 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
125 1.1 christos bits += 8;
126 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
127 1.1 christos bits += 8;
128 1.1 christos }
129 1.1 christos this = lcode[hold & lmask];
130 1.1 christos dolen:
131 1.1 christos op = (unsigned)(this.bits);
132 1.1 christos hold >>= op;
133 1.1 christos bits -= op;
134 1.1 christos op = (unsigned)(this.op);
135 1.1 christos if (op == 0) { /* literal */
136 1.1 christos Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
137 1.1 christos "inflate: literal '%c'\n" :
138 1.1 christos "inflate: literal 0x%02x\n", this.val));
139 1.1 christos PUP(out) = (unsigned char)(this.val);
140 1.1 christos }
141 1.1 christos else if (op & 16) { /* length base */
142 1.1 christos len = (unsigned)(this.val);
143 1.1 christos op &= 15; /* number of extra bits */
144 1.1 christos if (op) {
145 1.1 christos if (bits < op) {
146 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
147 1.1 christos bits += 8;
148 1.1 christos }
149 1.1 christos len += (unsigned)hold & ((1U << op) - 1);
150 1.1 christos hold >>= op;
151 1.1 christos bits -= op;
152 1.1 christos }
153 1.1 christos Tracevv((stderr, "inflate: length %u\n", len));
154 1.1 christos if (bits < 15) {
155 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
156 1.1 christos bits += 8;
157 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
158 1.1 christos bits += 8;
159 1.1 christos }
160 1.1 christos this = dcode[hold & dmask];
161 1.1 christos dodist:
162 1.1 christos op = (unsigned)(this.bits);
163 1.1 christos hold >>= op;
164 1.1 christos bits -= op;
165 1.1 christos op = (unsigned)(this.op);
166 1.1 christos if (op & 16) { /* distance base */
167 1.1 christos dist = (unsigned)(this.val);
168 1.1 christos op &= 15; /* number of extra bits */
169 1.1 christos if (bits < op) {
170 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
171 1.1 christos bits += 8;
172 1.1 christos if (bits < op) {
173 1.1 christos hold += (unsigned long)(PUP(in)) << bits;
174 1.1 christos bits += 8;
175 1.1 christos }
176 1.1 christos }
177 1.1 christos dist += (unsigned)hold & ((1U << op) - 1);
178 1.1 christos #ifdef INFLATE_STRICT
179 1.1 christos if (dist > dmax) {
180 1.1 christos strm->msg = (char *)"invalid distance too far back";
181 1.1 christos state->mode = BAD;
182 1.1 christos break;
183 1.1 christos }
184 1.1 christos #endif
185 1.1 christos hold >>= op;
186 1.1 christos bits -= op;
187 1.1 christos Tracevv((stderr, "inflate: distance %u\n", dist));
188 1.1 christos op = (unsigned)(out - beg); /* max distance in output */
189 1.1 christos if (dist > op) { /* see if copy from window */
190 1.1 christos op = dist - op; /* distance back in window */
191 1.1 christos if (op > whave) {
192 1.1 christos strm->msg = (char *)"invalid distance too far back";
193 1.1 christos state->mode = BAD;
194 1.1 christos break;
195 1.1 christos }
196 1.1 christos from = window - OFF;
197 1.1 christos if (write == 0) { /* very common case */
198 1.1 christos from += wsize - op;
199 1.1 christos if (op < len) { /* some from window */
200 1.1 christos len -= op;
201 1.1 christos do {
202 1.1 christos PUP(out) = PUP(from);
203 1.1 christos } while (--op);
204 1.1 christos from = out - dist; /* rest from output */
205 1.1 christos }
206 1.1 christos }
207 1.1 christos else if (write < op) { /* wrap around window */
208 1.1 christos from += wsize + write - op;
209 1.1 christos op -= write;
210 1.1 christos if (op < len) { /* some from end of window */
211 1.1 christos len -= op;
212 1.1 christos do {
213 1.1 christos PUP(out) = PUP(from);
214 1.1 christos } while (--op);
215 1.1 christos from = window - OFF;
216 1.1 christos if (write < len) { /* some from start of window */
217 1.1 christos op = write;
218 1.1 christos len -= op;
219 1.1 christos do {
220 1.1 christos PUP(out) = PUP(from);
221 1.1 christos } while (--op);
222 1.1 christos from = out - dist; /* rest from output */
223 1.1 christos }
224 1.1 christos }
225 1.1 christos }
226 1.1 christos else { /* contiguous in window */
227 1.1 christos from += write - op;
228 1.1 christos if (op < len) { /* some from window */
229 1.1 christos len -= op;
230 1.1 christos do {
231 1.1 christos PUP(out) = PUP(from);
232 1.1 christos } while (--op);
233 1.1 christos from = out - dist; /* rest from output */
234 1.1 christos }
235 1.1 christos }
236 1.1 christos while (len > 2) {
237 1.1 christos PUP(out) = PUP(from);
238 1.1 christos PUP(out) = PUP(from);
239 1.1 christos PUP(out) = PUP(from);
240 1.1 christos len -= 3;
241 1.1 christos }
242 1.1 christos if (len) {
243 1.1 christos PUP(out) = PUP(from);
244 1.1 christos if (len > 1)
245 1.1 christos PUP(out) = PUP(from);
246 1.1 christos }
247 1.1 christos }
248 1.1 christos else {
249 1.1 christos from = out - dist; /* copy direct from output */
250 1.1 christos do { /* minimum length is three */
251 1.1 christos PUP(out) = PUP(from);
252 1.1 christos PUP(out) = PUP(from);
253 1.1 christos PUP(out) = PUP(from);
254 1.1 christos len -= 3;
255 1.1 christos } while (len > 2);
256 1.1 christos if (len) {
257 1.1 christos PUP(out) = PUP(from);
258 1.1 christos if (len > 1)
259 1.1 christos PUP(out) = PUP(from);
260 1.1 christos }
261 1.1 christos }
262 1.1 christos }
263 1.1 christos else if ((op & 64) == 0) { /* 2nd level distance code */
264 1.1 christos this = dcode[this.val + (hold & ((1U << op) - 1))];
265 1.1 christos goto dodist;
266 1.1 christos }
267 1.1 christos else {
268 1.1 christos strm->msg = (char *)"invalid distance code";
269 1.1 christos state->mode = BAD;
270 1.1 christos break;
271 1.1 christos }
272 1.1 christos }
273 1.1 christos else if ((op & 64) == 0) { /* 2nd level length code */
274 1.1 christos this = lcode[this.val + (hold & ((1U << op) - 1))];
275 1.1 christos goto dolen;
276 1.1 christos }
277 1.1 christos else if (op & 32) { /* end-of-block */
278 1.1 christos Tracevv((stderr, "inflate: end of block\n"));
279 1.1 christos state->mode = TYPE;
280 1.1 christos break;
281 1.1 christos }
282 1.1 christos else {
283 1.1 christos strm->msg = (char *)"invalid literal/length code";
284 1.1 christos state->mode = BAD;
285 1.1 christos break;
286 1.1 christos }
287 1.1 christos } while (in < last && out < end);
288 1.1 christos
289 1.1 christos /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
290 1.1 christos len = bits >> 3;
291 1.1 christos in -= len;
292 1.1 christos bits -= len << 3;
293 1.1 christos hold &= (1U << bits) - 1;
294 1.1 christos
295 1.1 christos /* update state and return */
296 1.1 christos strm->next_in = in + OFF;
297 1.1 christos strm->next_out = out + OFF;
298 1.1 christos strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
299 1.1 christos strm->avail_out = (unsigned)(out < end ?
300 1.1 christos 257 + (end - out) : 257 - (out - end));
301 1.1 christos state->hold = hold;
302 1.1 christos state->bits = bits;
303 1.1 christos return;
304 1.1 christos }
305 1.1 christos
306 1.1 christos /*
307 1.1 christos inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
308 1.1 christos - Using bit fields for code structure
309 1.1 christos - Different op definition to avoid & for extra bits (do & for table bits)
310 1.1 christos - Three separate decoding do-loops for direct, window, and write == 0
311 1.1 christos - Special case for distance > 1 copies to do overlapped load and store copy
312 1.1 christos - Explicit branch predictions (based on measured branch probabilities)
313 1.1 christos - Deferring match copy and interspersed it with decoding subsequent codes
314 1.1 christos - Swapping literal/length else
315 1.1 christos - Swapping window/direct else
316 1.1 christos - Larger unrolled copy loops (three is about right)
317 1.1 christos - Moving len -= 3 statement into middle of loop
318 1.1 christos */
319 1.1 christos
320 1.1 christos #endif /* !ASMINF */
321