1 /* inffas86.c is a hand tuned assembler version of
3 * inffast.c -- fast decoding
4 * Copyright (C) 1995-2003 Mark Adler
5 * For conditions of distribution and use, see copyright notice in zlib.h
7 * Copyright (C) 2003 Chris Anderson <christop@charm.net>
8 * Please use the copyright conditions above.
10 * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
11 * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at
12 * the moment. I have successfully compiled and tested this code with gcc2.96,
13 * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S
14 * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
15 * enabled. I will attempt to merge the MMX code into this version. Newer
16 * versions of this and inffast.S can be found at
17 * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
25 /* Mark Adler's comments from inffast.c: */
28 Decode literal, length, and distance codes and write out the resulting
29 literal and match bytes until either not enough input or output is
30 available, an end-of-block is encountered, or a data error is encountered.
31 When large enough input and output buffers are supplied to inflate(), for
32 example, a 16K input buffer and a 64K output buffer, more than 95% of the
33 inflate execution time is spent in this routine.
39 strm->avail_out >= 258
40 start >= strm->avail_out
43 On return, state->mode is one of:
45 LEN -- ran out of enough output space or enough available input
46 TYPE -- reached end of block code, inflate() to interpret next block
47 BAD -- error in block data
51 - The maximum input bits used by a length/distance pair is 15 bits for the
52 length code, 5 bits for the length extra, 15 bits for the distance code,
53 and 13 bits for the distance extra. This totals 48 bits, or six bytes.
54 Therefore if strm->avail_in >= 6, then there is enough input to avoid
55 checking for available input while decoding.
57 - The maximum bytes that a single length/distance pair can output is 258
58 bytes, which is the maximum length that can be coded. inflate_fast()
59 requires strm->avail_out >= 258 for each loop to avoid checking for
62 void inflate_fast(strm, start)
64 unsigned start; /* inflate()'s starting value for strm->avail_out */
66 struct inflate_state FAR *state;
68 void *esp; /* esp save */
69 unsigned char FAR *in; /* local strm->next_in */
70 unsigned char FAR *last; /* while in < last, enough input available */
71 unsigned char FAR *out; /* local strm->next_out */
72 unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
73 unsigned char FAR *end; /* while out < end, enough space available */
74 unsigned wsize; /* window size or zero if not using window */
75 unsigned write; /* window write index */
76 unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
77 unsigned long hold; /* local strm->hold */
78 unsigned bits; /* local strm->bits */
79 code const FAR *lcode; /* local strm->lencode */
80 code const FAR *dcode; /* local strm->distcode */
81 unsigned lmask; /* mask for first level of length codes */
82 unsigned dmask; /* mask for first level of distance codes */
83 unsigned len; /* match length, unused bytes */
84 unsigned dist; /* match distance */
85 unsigned status; /* this is set when state changes */
88 /* copy state to local variables */
89 state = (struct inflate_state FAR *)strm->state;
90 ar.in = strm->next_in;
91 ar.last = ar.in + (strm->avail_in - 5);
92 ar.out = strm->next_out;
93 ar.beg = ar.out - (start - strm->avail_out);
94 ar.end = ar.out + (strm->avail_out - 257);
95 ar.wsize = state->wsize;
96 ar.write = state->write;
97 ar.window = state->window;
98 ar.hold = state->hold;
99 ar.bits = state->bits;
100 ar.lcode = state->lencode;
101 ar.dcode = state->distcode;
102 ar.lmask = (1U << state->lenbits) - 1;
103 ar.dmask = (1U << state->distbits) - 1;
105 /* decode literals and length/distances until end-of-block or not enough
106 input data or output space */
108 /* align in on 2 byte boundary */
109 if (((unsigned long)(void *)ar.in & 0x1) != 0) {
110 ar.hold += (unsigned long)*ar.in++ << ar.bits;
114 #if defined( __GNUC__ ) || defined( __ICC )
115 __asm__ __volatile__ (
119 " movl %%esp, (%%eax)\n"
120 " movl %%eax, %%esp\n"
121 " movl 4(%%esp), %%esi\n" /* esi = in */
122 " movl 12(%%esp), %%edi\n" /* edi = out */
123 " movl 36(%%esp), %%edx\n" /* edx = hold */
124 " movl 40(%%esp), %%ebx\n" /* ebx = bits */
125 " movl 44(%%esp), %%ebp\n" /* ebp = lcode */
131 " cmpl %%edi, 20(%%esp)\n"
132 " jbe .L_break_loop\n"
133 " cmpl %%esi, 8(%%esp)\n"
134 " jbe .L_break_loop\n"
138 " ja .L_get_length_code\n" /* if (15 < bits) */
140 " xorl %%eax, %%eax\n"
141 " lodsw\n" /* al = *(ushort *)in++ */
142 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */
143 " addb $16, %%bl\n" /* bits += 16 */
144 " shll %%cl, %%eax\n"
145 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */
147 ".L_get_length_code:\n"
148 " movl 52(%%esp), %%eax\n" /* eax = lmask */
149 " andl %%edx, %%eax\n" /* eax &= hold */
150 " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */
153 " movb %%ah, %%cl\n" /* cl = this.bits */
154 " subb %%ah, %%bl\n" /* bits -= this.bits */
155 " shrl %%cl, %%edx\n" /* hold >>= this.bits */
157 " testb %%al, %%al\n"
158 " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */
160 " shrl $16, %%eax\n" /* output this.val char */
162 " jmp .L_while_test\n"
164 ".L_test_for_length_base:\n"
165 " movl %%eax, %%ecx\n" /* len = this */
166 " shrl $16, %%ecx\n" /* len = this.val */
167 " movl %%ecx, 60(%%esp)\n" /* len = this */
171 " jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
172 " andb $15, %%cl\n" /* op &= 15 */
173 " jz .L_decode_distance\n" /* if (!op) */
175 " jae .L_add_bits_to_len\n" /* if (op <= bits) */
177 " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */
178 " xorl %%eax, %%eax\n"
179 " lodsw\n" /* al = *(ushort *)in++ */
180 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */
181 " addb $16, %%bl\n" /* bits += 16 */
182 " shll %%cl, %%eax\n"
183 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */
184 " movb %%ch, %%cl\n" /* move op back to ecx */
186 ".L_add_bits_to_len:\n"
188 " shll %%cl, %%eax\n"
191 " andl %%edx, %%eax\n" /* eax &= hold */
192 " shrl %%cl, %%edx\n"
193 " addl %%eax, 60(%%esp)\n" /* len += hold & mask[op] */
195 ".L_decode_distance:\n"
197 " ja .L_get_distance_code\n" /* if (15 < bits) */
199 " xorl %%eax, %%eax\n"
200 " lodsw\n" /* al = *(ushort *)in++ */
201 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */
202 " addb $16, %%bl\n" /* bits += 16 */
203 " shll %%cl, %%eax\n"
204 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */
206 ".L_get_distance_code:\n"
207 " movl 56(%%esp), %%eax\n" /* eax = dmask */
208 " movl 48(%%esp), %%ecx\n" /* ecx = dcode */
209 " andl %%edx, %%eax\n" /* eax &= hold */
210 " movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */
213 " movl %%eax, %%ebp\n" /* dist = this */
214 " shrl $16, %%ebp\n" /* dist = this.val */
216 " subb %%ah, %%bl\n" /* bits -= this.bits */
217 " shrl %%cl, %%edx\n" /* hold >>= this.bits */
218 " movb %%al, %%cl\n" /* cl = this.op */
220 " testb $16, %%al\n" /* if ((op & 16) == 0) */
221 " jz .L_test_for_second_level_dist\n"
222 " andb $15, %%cl\n" /* op &= 15 */
223 " jz .L_check_dist_one\n"
225 " jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */
227 " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */
228 " xorl %%eax, %%eax\n"
229 " lodsw\n" /* al = *(ushort *)in++ */
230 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */
231 " addb $16, %%bl\n" /* bits += 16 */
232 " shll %%cl, %%eax\n"
233 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */
234 " movb %%ch, %%cl\n" /* move op back to ecx */
236 ".L_add_bits_to_dist:\n"
238 " shll %%cl, %%eax\n"
239 " decl %%eax\n" /* (1 << op) - 1 */
241 " andl %%edx, %%eax\n" /* eax &= hold */
242 " shrl %%cl, %%edx\n"
243 " addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */
246 " movl %%esi, 4(%%esp)\n" /* save in so from can use it's reg */
247 " movl %%edi, %%eax\n"
248 " subl 16(%%esp), %%eax\n" /* nbytes = out - beg */
250 " cmpl %%ebp, %%eax\n"
251 " jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */
253 " movl 60(%%esp), %%ecx\n"
254 " movl %%edi, %%esi\n"
255 " subl %%ebp, %%esi\n" /* from = out - dist */
257 " subl $3, %%ecx\n" /* copy from to out */
258 " movb (%%esi), %%al\n"
259 " movb %%al, (%%edi)\n"
260 " movb 1(%%esi), %%al\n"
261 " movb 2(%%esi), %%ah\n"
263 " movb %%al, 1(%%edi)\n"
264 " movb %%ah, 2(%%edi)\n"
268 " movl 4(%%esp), %%esi\n" /* move in back to %esi, toss from */
269 " movl 44(%%esp), %%ebp\n" /* ebp = lcode */
270 " jmp .L_while_test\n"
272 ".L_check_dist_one:\n"
273 " cmpl $1, %%ebp\n" /* if dist 1, is a memset */
274 " jne .L_check_window\n"
275 " cmpl %%edi, 16(%%esp)\n"
276 " je .L_check_window\n"
279 " movl 60(%%esp), %%ecx\n"
280 " movb (%%edi), %%al\n"
283 " movb %%al, 1(%%edi)\n" /* memset out with from[-1] */
284 " movb %%al, 2(%%edi)\n"
285 " movb %%al, 3(%%edi)\n"
288 " movl 44(%%esp), %%ebp\n" /* ebp = lcode */
289 " jmp .L_while_test\n"
291 ".L_test_for_second_level_length:\n"
293 " jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
296 " shll %%cl, %%eax\n"
298 " andl %%edx, %%eax\n" /* eax &= hold */
299 " addl 60(%%esp), %%eax\n" /* eax += this.val */
300 " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
303 ".L_test_for_second_level_dist:\n"
305 " jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
308 " shll %%cl, %%eax\n"
310 " andl %%edx, %%eax\n" /* eax &= hold */
311 " addl %%ebp, %%eax\n" /* eax += this.val */
312 " movl 48(%%esp), %%ecx\n" /* ecx = dcode */
313 " movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
317 " movl %%eax, %%ecx\n"
318 " movl 24(%%esp), %%eax\n" /* prepare for dist compare */
319 " negl %%ecx\n" /* nbytes = -nbytes */
320 " movl 32(%%esp), %%esi\n" /* from = window */
322 " cmpl %%ebp, %%eax\n"
323 " jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */
325 " addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */
326 " cmpl $0, 28(%%esp)\n"
327 " jne .L_wrap_around_window\n" /* if (write != 0) */
329 " subl %%ecx, %%eax\n"
330 " addl %%eax, %%esi\n" /* from += wsize - nbytes */
332 " movl 60(%%esp), %%eax\n"
333 " cmpl %%ecx, %%eax\n"
334 " jbe .L_do_copy1\n" /* if (nbytes >= len) */
336 " subl %%ecx, %%eax\n" /* len -= nbytes */
338 " movl %%edi, %%esi\n"
339 " subl %%ebp, %%esi\n" /* from = out - dist */
342 " cmpl %%ecx, %%eax\n"
343 " jbe .L_do_copy1\n" /* if (nbytes >= len) */
345 " subl %%ecx, %%eax\n" /* len -= nbytes */
347 " movl %%edi, %%esi\n"
348 " subl %%ebp, %%esi\n" /* from = out - dist */
351 ".L_wrap_around_window:\n"
352 " movl 28(%%esp), %%eax\n"
353 " cmpl %%eax, %%ecx\n"
354 " jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */
356 " addl 24(%%esp), %%esi\n"
357 " addl %%eax, %%esi\n"
358 " subl %%ecx, %%esi\n" /* from += wsize + write - nbytes */
359 " subl %%eax, %%ecx\n" /* nbytes -= write */
361 " movl 60(%%esp), %%eax\n"
362 " cmpl %%ecx, %%eax\n"
363 " jbe .L_do_copy1\n" /* if (nbytes >= len) */
365 " subl %%ecx, %%eax\n" /* len -= nbytes */
367 " movl 32(%%esp), %%esi\n" /* from = window */
368 " movl 28(%%esp), %%ecx\n" /* nbytes = write */
369 " cmpl %%ecx, %%eax\n"
370 " jbe .L_do_copy1\n" /* if (nbytes >= len) */
372 " subl %%ecx, %%eax\n" /* len -= nbytes */
374 " movl %%edi, %%esi\n"
375 " subl %%ebp, %%esi\n" /* from = out - dist */
378 ".L_contiguous_in_window:\n"
379 " addl %%eax, %%esi\n"
380 " subl %%ecx, %%esi\n" /* from += write - nbytes */
382 " movl 60(%%esp), %%eax\n"
383 " cmpl %%ecx, %%eax\n"
384 " jbe .L_do_copy1\n" /* if (nbytes >= len) */
386 " subl %%ecx, %%eax\n" /* len -= nbytes */
388 " movl %%edi, %%esi\n"
389 " subl %%ebp, %%esi\n" /* from = out - dist */
392 " movl %%eax, %%ecx\n"
395 " movl 4(%%esp), %%esi\n" /* move in back to %esi, toss from */
396 " movl 44(%%esp), %%ebp\n" /* ebp = lcode */
397 " jmp .L_while_test\n"
399 ".L_test_for_end_of_block:\n"
401 " jz .L_invalid_literal_length_code\n"
402 " movl $1, 68(%%esp)\n"
403 " jmp .L_break_loop_with_status\n"
405 ".L_invalid_literal_length_code:\n"
406 " movl $2, 68(%%esp)\n"
407 " jmp .L_break_loop_with_status\n"
409 ".L_invalid_distance_code:\n"
410 " movl $3, 68(%%esp)\n"
411 " jmp .L_break_loop_with_status\n"
413 ".L_invalid_distance_too_far:\n"
414 " movl 4(%%esp), %%esi\n"
415 " movl $4, 68(%%esp)\n"
416 " jmp .L_break_loop_with_status\n"
419 " movl $0, 68(%%esp)\n"
421 ".L_break_loop_with_status:\n"
422 /* put in, out, bits, and hold back into ar and pop esp */
423 " movl %%esi, 4(%%esp)\n"
424 " movl %%edi, 12(%%esp)\n"
425 " movl %%ebx, 40(%%esp)\n"
426 " movl %%edx, 36(%%esp)\n"
427 " movl (%%esp), %%esp\n"
432 : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
434 #elif defined( _MSC_VER )
441 mov esi, [esp+4] /* esi = in */
442 mov edi, [esp+12] /* edi = out */
443 mov edx, [esp+36] /* edx = hold */
444 mov ebx, [esp+40] /* ebx = bits */
445 mov ebp, [esp+44] /* ebp = lcode */
458 ja L_get_length_code /* if (15 < bits) */
461 lodsw /* al = *(ushort *)in++ */
462 mov cl, bl /* cl = bits, needs it for shifting */
463 add bl, 16 /* bits += 16 */
465 or edx, eax /* hold |= *((ushort *)in)++ << bits */
468 mov eax, [esp+52] /* eax = lmask */
469 and eax, edx /* eax &= hold */
470 mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
473 mov cl, ah /* cl = this.bits */
474 sub bl, ah /* bits -= this.bits */
475 shr edx, cl /* hold >>= this.bits */
478 jnz L_test_for_length_base /* if (op != 0) 45.7% */
480 shr eax, 16 /* output this.val char */
484 L_test_for_length_base:
485 mov ecx, eax /* len = this */
486 shr ecx, 16 /* len = this.val */
487 mov [esp+60], ecx /* len = this */
491 jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
492 and cl, 15 /* op &= 15 */
493 jz L_decode_distance /* if (!op) */
495 jae L_add_bits_to_len /* if (op <= bits) */
497 mov ch, cl /* stash op in ch, freeing cl */
499 lodsw /* al = *(ushort *)in++ */
500 mov cl, bl /* cl = bits, needs it for shifting */
501 add bl, 16 /* bits += 16 */
503 or edx, eax /* hold |= *((ushort *)in)++ << bits */
504 mov cl, ch /* move op back to ecx */
511 and eax, edx /* eax &= hold */
513 add [esp+60], eax /* len += hold & mask[op] */
517 ja L_get_distance_code /* if (15 < bits) */
520 lodsw /* al = *(ushort *)in++ */
521 mov cl, bl /* cl = bits, needs it for shifting */
522 add bl, 16 /* bits += 16 */
524 or edx, eax /* hold |= *((ushort *)in)++ << bits */
527 mov eax, [esp+56] /* eax = dmask */
528 mov ecx, [esp+48] /* ecx = dcode */
529 and eax, edx /* eax &= hold */
530 mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
533 mov ebp, eax /* dist = this */
534 shr ebp, 16 /* dist = this.val */
536 sub bl, ah /* bits -= this.bits */
537 shr edx, cl /* hold >>= this.bits */
538 mov cl, al /* cl = this.op */
540 test al, 16 /* if ((op & 16) == 0) */
541 jz L_test_for_second_level_dist
542 and cl, 15 /* op &= 15 */
545 jae L_add_bits_to_dist /* if (op <= bits) 97.6% */
547 mov ch, cl /* stash op in ch, freeing cl */
549 lodsw /* al = *(ushort *)in++ */
550 mov cl, bl /* cl = bits, needs it for shifting */
551 add bl, 16 /* bits += 16 */
553 or edx, eax /* hold |= *((ushort *)in)++ << bits */
554 mov cl, ch /* move op back to ecx */
559 dec eax /* (1 << op) - 1 */
561 and eax, edx /* eax &= hold */
563 add ebp, eax /* dist += hold & ((1 << op) - 1) */
566 mov [esp+4], esi /* save in so from can use it's reg */
568 sub eax, [esp+16] /* nbytes = out - beg */
571 jb L_clip_window /* if (dist > nbytes) 4.2% */
575 sub esi, ebp /* from = out - dist */
577 sub ecx, 3 /* copy from to out */
588 mov esi, [esp+4] /* move in back to %esi, toss from */
589 mov ebp, [esp+44] /* ebp = lcode */
593 cmp ebp, 1 /* if dist 1, is a memset */
603 mov [edi+1], al /* memset out with from[-1] */
608 mov ebp, [esp+44] /* ebp = lcode */
611 L_test_for_second_level_length:
613 jnz L_test_for_end_of_block /* if ((op & 64) != 0) */
618 and eax, edx /* eax &= hold */
619 add eax, [esp+60] /* eax += this.val */
620 mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
623 L_test_for_second_level_dist:
625 jnz L_invalid_distance_code /* if ((op & 64) != 0) */
630 and eax, edx /* eax &= hold */
631 add eax, ebp /* eax += this.val */
632 mov ecx, [esp+48] /* ecx = dcode */
633 mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
638 mov eax, [esp+24] /* prepare for dist compare */
639 neg ecx /* nbytes = -nbytes */
640 mov esi, [esp+32] /* from = window */
643 jb L_invalid_distance_too_far /* if (dist > wsize) */
645 add ecx, ebp /* nbytes = dist - nbytes */
646 cmp dword ptr [esp+28], 0
647 jne L_wrap_around_window /* if (write != 0) */
650 add esi, eax /* from += wsize - nbytes */
654 jbe L_do_copy1 /* if (nbytes >= len) */
656 sub eax, ecx /* len -= nbytes */
659 sub esi, ebp /* from = out - dist */
663 jbe L_do_copy1 /* if (nbytes >= len) */
665 sub eax, ecx /* len -= nbytes */
668 sub esi, ebp /* from = out - dist */
671 L_wrap_around_window:
674 jbe L_contiguous_in_window /* if (write >= nbytes) */
678 sub esi, ecx /* from += wsize + write - nbytes */
679 sub ecx, eax /* nbytes -= write */
683 jbe L_do_copy1 /* if (nbytes >= len) */
685 sub eax, ecx /* len -= nbytes */
687 mov esi, [esp+32] /* from = window */
688 mov ecx, [esp+28] /* nbytes = write */
690 jbe L_do_copy1 /* if (nbytes >= len) */
692 sub eax, ecx /* len -= nbytes */
695 sub esi, ebp /* from = out - dist */
698 L_contiguous_in_window:
700 sub esi, ecx /* from += write - nbytes */
704 jbe L_do_copy1 /* if (nbytes >= len) */
706 sub eax, ecx /* len -= nbytes */
709 sub esi, ebp /* from = out - dist */
715 mov esi, [esp+4] /* move in back to %esi, toss from */
716 mov ebp, [esp+44] /* ebp = lcode */
719 L_test_for_end_of_block:
721 jz L_invalid_literal_length_code
722 mov dword ptr [esp+68], 1
723 jmp L_break_loop_with_status
725 L_invalid_literal_length_code:
726 mov dword ptr [esp+68], 2
727 jmp L_break_loop_with_status
729 L_invalid_distance_code:
730 mov dword ptr [esp+68], 3
731 jmp L_break_loop_with_status
733 L_invalid_distance_too_far:
735 mov dword ptr [esp+68], 4
736 jmp L_break_loop_with_status
739 mov dword ptr [esp+68], 0
741 L_break_loop_with_status:
742 /* put in, out, bits, and hold back into ar and pop esp */
755 strm->msg = "invalid literal/length code";
756 else if (ar.status == 3)
757 strm->msg = "invalid distance code";
759 strm->msg = "invalid distance too far back";
762 else if ( ar.status == 1 ) {
766 /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
767 ar.len = ar.bits >> 3;
769 ar.bits -= ar.len << 3;
770 ar.hold &= (1U << ar.bits) - 1;
772 /* update state and return */
773 strm->next_in = ar.in;
774 strm->next_out = ar.out;
775 strm->avail_in = (unsigned)(ar.in < ar.last ? 5 + (ar.last - ar.in) :
776 5 - (ar.in - ar.last));
777 strm->avail_out = (unsigned)(ar.out < ar.end ? 257 + (ar.end - ar.out) :
778 257 - (ar.out - ar.end));
779 state->hold = ar.hold;
780 state->bits = ar.bits;