1 /* inffas86.c is a hand tuned assembler version of 2 * 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 6 * 7 * Copyright (C) 2003 Chris Anderson <christop (at) charm.net> 8 * Please use the copyright conditions above. 9 * 10 * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also 11 * slightly quicker on x86 systems because, instead of using rep movsb to copy 12 * data, it uses rep movsw, which moves data in 2-byte chunks instead of single 13 * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates 14 * from http://fedora.linux.duke.edu/fc1_x86_64 15 * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with 16 * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, 17 * when decompressing mozilla-source-1.3.tar.gz. 18 * 19 * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from 20 * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at 21 * the moment. I have successfully compiled and tested this code with gcc2.96, 22 * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S 23 * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX 24 * enabled. I will attempt to merge the MMX code into this version. Newer 25 * versions of this and inffast.S can be found at 26 * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ 27 */ 28 29 #include "zutil.h" 30 #include "inftrees.h" 31 #include "inflate.h" 32 #include "inffast.h" 33 34 /* Mark Adler's comments from inffast.c: */ 35 36 /* 37 Decode literal, length, and distance codes and write out the resulting 38 literal and match bytes until either not enough input or output is 39 available, an end-of-block is encountered, or a data error is encountered. 40 When large enough input and output buffers are supplied to inflate(), for 41 example, a 16K input buffer and a 64K output buffer, more than 95% of the 42 inflate execution time is spent in this routine. 43 44 Entry assumptions: 45 46 state->mode == LEN 47 strm->avail_in >= 6 48 strm->avail_out >= 258 49 start >= strm->avail_out 50 state->bits < 8 51 52 On return, state->mode is one of: 53 54 LEN -- ran out of enough output space or enough available input 55 TYPE -- reached end of block code, inflate() to interpret next block 56 BAD -- error in block data 57 58 Notes: 59 60 - The maximum input bits used by a length/distance pair is 15 bits for the 61 length code, 5 bits for the length extra, 15 bits for the distance code, 62 and 13 bits for the distance extra. This totals 48 bits, or six bytes. 63 Therefore if strm->avail_in >= 6, then there is enough input to avoid 64 checking for available input while decoding. 65 66 - The maximum bytes that a single length/distance pair can output is 258 67 bytes, which is the maximum length that can be coded. inflate_fast() 68 requires strm->avail_out >= 258 for each loop to avoid checking for 69 output space. 70 */ 71 void inflate_fast(strm, start) 72 z_streamp strm; 73 unsigned start; /* inflate()'s starting value for strm->avail_out */ 74 { 75 struct inflate_state FAR *state; 76 struct inffast_ar { 77 /* 64 32 x86 x86_64 */ 78 /* ar offset register */ 79 /* 0 0 */ void *esp; /* esp save */ 80 /* 8 4 */ void *ebp; /* ebp save */ 81 /* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ 82 /* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ 83 /* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ 84 /* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ 85 /* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ 86 /* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ 87 /* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ 88 /* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ 89 /* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ 90 /* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ 91 /* 92 48 */ unsigned wsize; /* window size */ 92 /* 96 52 */ unsigned write; /* window write index */ 93 /*100 56 */ unsigned lmask; /* r12 mask for lcode */ 94 /*104 60 */ unsigned dmask; /* r13 mask for dcode */ 95 /*108 64 */ unsigned len; /* r14 match length */ 96 /*112 68 */ unsigned dist; /* r15 match distance */ 97 /*116 72 */ unsigned status; /* set when state chng*/ 98 } ar; 99 100 #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) 101 #define PAD_AVAIL_IN 6 102 #define PAD_AVAIL_OUT 258 103 #else 104 #define PAD_AVAIL_IN 5 105 #define PAD_AVAIL_OUT 257 106 #endif 107 108 /* copy state to local variables */ 109 state = (struct inflate_state FAR *)strm->state; 110 ar.in = strm->next_in; 111 ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); 112 ar.out = strm->next_out; 113 ar.beg = ar.out - (start - strm->avail_out); 114 ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); 115 ar.wsize = state->wsize; 116 ar.write = state->wnext; 117 ar.window = state->window; 118 ar.hold = state->hold; 119 ar.bits = state->bits; 120 ar.lcode = state->lencode; 121 ar.dcode = state->distcode; 122 ar.lmask = (1U << state->lenbits) - 1; 123 ar.dmask = (1U << state->distbits) - 1; 124 125 /* decode literals and length/distances until end-of-block or not enough 126 input data or output space */ 127 128 /* align in on 1/2 hold size boundary */ 129 while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { 130 ar.hold += (unsigned long)*ar.in++ << ar.bits; 131 ar.bits += 8; 132 } 133 134 #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) 135 __asm__ __volatile__ ( 136 " leaq %0, %%rax\n" 137 " movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ 138 " movq %%rsp, (%%rax)\n" 139 " movq %%rax, %%rsp\n" /* make rsp point to &ar */ 140 " movq 16(%%rsp), %%rsi\n" /* rsi = in */ 141 " movq 32(%%rsp), %%rdi\n" /* rdi = out */ 142 " movq 24(%%rsp), %%r9\n" /* r9 = last */ 143 " movq 48(%%rsp), %%r10\n" /* r10 = end */ 144 " movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ 145 " movq 72(%%rsp), %%r11\n" /* r11 = dcode */ 146 " movq 80(%%rsp), %%rdx\n" /* rdx = hold */ 147 " movl 88(%%rsp), %%ebx\n" /* ebx = bits */ 148 " movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ 149 " movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ 150 /* r14d = len */ 151 /* r15d = dist */ 152 " cld\n" 153 " cmpq %%rdi, %%r10\n" 154 " je .L_one_time\n" /* if only one decode left */ 155 " cmpq %%rsi, %%r9\n" 156 " je .L_one_time\n" 157 " jmp .L_do_loop\n" 158 159 ".L_one_time:\n" 160 " movq %%r12, %%r8\n" /* r8 = lmask */ 161 " cmpb $32, %%bl\n" 162 " ja .L_get_length_code_one_time\n" 163 164 " lodsl\n" /* eax = *(uint *)in++ */ 165 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 166 " addb $32, %%bl\n" /* bits += 32 */ 167 " shlq %%cl, %%rax\n" 168 " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ 169 " jmp .L_get_length_code_one_time\n" 170 171 ".align 32,0x90\n" 172 ".L_while_test:\n" 173 " cmpq %%rdi, %%r10\n" 174 " jbe .L_break_loop\n" 175 " cmpq %%rsi, %%r9\n" 176 " jbe .L_break_loop\n" 177 178 ".L_do_loop:\n" 179 " movq %%r12, %%r8\n" /* r8 = lmask */ 180 " cmpb $32, %%bl\n" 181 " ja .L_get_length_code\n" /* if (32 < bits) */ 182 183 " lodsl\n" /* eax = *(uint *)in++ */ 184 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 185 " addb $32, %%bl\n" /* bits += 32 */ 186 " shlq %%cl, %%rax\n" 187 " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ 188 189 ".L_get_length_code:\n" 190 " andq %%rdx, %%r8\n" /* r8 &= hold */ 191 " movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ 192 193 " movb %%ah, %%cl\n" /* cl = this.bits */ 194 " subb %%ah, %%bl\n" /* bits -= this.bits */ 195 " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ 196 197 " testb %%al, %%al\n" 198 " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ 199 200 " movq %%r12, %%r8\n" /* r8 = lmask */ 201 " shrl $16, %%eax\n" /* output this.val char */ 202 " stosb\n" 203 204 ".L_get_length_code_one_time:\n" 205 " andq %%rdx, %%r8\n" /* r8 &= hold */ 206 " movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ 207 208 ".L_dolen:\n" 209 " movb %%ah, %%cl\n" /* cl = this.bits */ 210 " subb %%ah, %%bl\n" /* bits -= this.bits */ 211 " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ 212 213 " testb %%al, %%al\n" 214 " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ 215 216 " shrl $16, %%eax\n" /* output this.val char */ 217 " stosb\n" 218 " jmp .L_while_test\n" 219 220 ".align 32,0x90\n" 221 ".L_test_for_length_base:\n" 222 " movl %%eax, %%r14d\n" /* len = this */ 223 " shrl $16, %%r14d\n" /* len = this.val */ 224 " movb %%al, %%cl\n" 225 226 " testb $16, %%al\n" 227 " jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ 228 " andb $15, %%cl\n" /* op &= 15 */ 229 " jz .L_decode_distance\n" /* if (!op) */ 230 231 ".L_add_bits_to_len:\n" 232 " subb %%cl, %%bl\n" 233 " xorl %%eax, %%eax\n" 234 " incl %%eax\n" 235 " shll %%cl, %%eax\n" 236 " decl %%eax\n" 237 " andl %%edx, %%eax\n" /* eax &= hold */ 238 " shrq %%cl, %%rdx\n" 239 " addl %%eax, %%r14d\n" /* len += hold & mask[op] */ 240 241 ".L_decode_distance:\n" 242 " movq %%r13, %%r8\n" /* r8 = dmask */ 243 " cmpb $32, %%bl\n" 244 " ja .L_get_distance_code\n" /* if (32 < bits) */ 245 246 " lodsl\n" /* eax = *(uint *)in++ */ 247 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 248 " addb $32, %%bl\n" /* bits += 32 */ 249 " shlq %%cl, %%rax\n" 250 " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ 251 252 ".L_get_distance_code:\n" 253 " andq %%rdx, %%r8\n" /* r8 &= hold */ 254 " movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ 255 256 ".L_dodist:\n" 257 " movl %%eax, %%r15d\n" /* dist = this */ 258 " shrl $16, %%r15d\n" /* dist = this.val */ 259 " movb %%ah, %%cl\n" 260 " subb %%ah, %%bl\n" /* bits -= this.bits */ 261 " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ 262 " movb %%al, %%cl\n" /* cl = this.op */ 263 264 " testb $16, %%al\n" /* if ((op & 16) == 0) */ 265 " jz .L_test_for_second_level_dist\n" 266 " andb $15, %%cl\n" /* op &= 15 */ 267 " jz .L_check_dist_one\n" 268 269 ".L_add_bits_to_dist:\n" 270 " subb %%cl, %%bl\n" 271 " xorl %%eax, %%eax\n" 272 " incl %%eax\n" 273 " shll %%cl, %%eax\n" 274 " decl %%eax\n" /* (1 << op) - 1 */ 275 " andl %%edx, %%eax\n" /* eax &= hold */ 276 " shrq %%cl, %%rdx\n" 277 " addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ 278 279 ".L_check_window:\n" 280 " movq %%rsi, %%r8\n" /* save in so from can use it's reg */ 281 " movq %%rdi, %%rax\n" 282 " subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ 283 284 " cmpl %%r15d, %%eax\n" 285 " jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ 286 287 " movl %%r14d, %%ecx\n" /* ecx = len */ 288 " movq %%rdi, %%rsi\n" 289 " subq %%r15, %%rsi\n" /* from = out - dist */ 290 291 " sarl %%ecx\n" 292 " jnc .L_copy_two\n" /* if len % 2 == 0 */ 293 294 " rep movsw\n" 295 " movb (%%rsi), %%al\n" 296 " movb %%al, (%%rdi)\n" 297 " incq %%rdi\n" 298 299 " movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ 300 " jmp .L_while_test\n" 301 302 ".L_copy_two:\n" 303 " rep movsw\n" 304 " movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ 305 " jmp .L_while_test\n" 306 307 ".align 32,0x90\n" 308 ".L_check_dist_one:\n" 309 " cmpl $1, %%r15d\n" /* if dist 1, is a memset */ 310 " jne .L_check_window\n" 311 " cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ 312 " je .L_check_window\n" 313 314 " movl %%r14d, %%ecx\n" /* ecx = len */ 315 " movb -1(%%rdi), %%al\n" 316 " movb %%al, %%ah\n" 317 318 " sarl %%ecx\n" 319 " jnc .L_set_two\n" 320 " movb %%al, (%%rdi)\n" 321 " incq %%rdi\n" 322 323 ".L_set_two:\n" 324 " rep stosw\n" 325 " jmp .L_while_test\n" 326 327 ".align 32,0x90\n" 328 ".L_test_for_second_level_length:\n" 329 " testb $64, %%al\n" 330 " jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ 331 332 " xorl %%eax, %%eax\n" 333 " incl %%eax\n" 334 " shll %%cl, %%eax\n" 335 " decl %%eax\n" 336 " andl %%edx, %%eax\n" /* eax &= hold */ 337 " addl %%r14d, %%eax\n" /* eax += len */ 338 " movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ 339 " jmp .L_dolen\n" 340 341 ".align 32,0x90\n" 342 ".L_test_for_second_level_dist:\n" 343 " testb $64, %%al\n" 344 " jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ 345 346 " xorl %%eax, %%eax\n" 347 " incl %%eax\n" 348 " shll %%cl, %%eax\n" 349 " decl %%eax\n" 350 " andl %%edx, %%eax\n" /* eax &= hold */ 351 " addl %%r15d, %%eax\n" /* eax += dist */ 352 " movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ 353 " jmp .L_dodist\n" 354 355 ".align 32,0x90\n" 356 ".L_clip_window:\n" 357 " movl %%eax, %%ecx\n" /* ecx = nbytes */ 358 " movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ 359 " negl %%ecx\n" /* nbytes = -nbytes */ 360 361 " cmpl %%r15d, %%eax\n" 362 " jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ 363 364 " addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ 365 " cmpl $0, 96(%%rsp)\n" 366 " jne .L_wrap_around_window\n" /* if (write != 0) */ 367 368 " movq 56(%%rsp), %%rsi\n" /* from = window */ 369 " subl %%ecx, %%eax\n" /* eax -= nbytes */ 370 " addq %%rax, %%rsi\n" /* from += wsize - nbytes */ 371 372 " movl %%r14d, %%eax\n" /* eax = len */ 373 " cmpl %%ecx, %%r14d\n" 374 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 375 376 " subl %%ecx, %%eax\n" /* eax -= nbytes */ 377 " rep movsb\n" 378 " movq %%rdi, %%rsi\n" 379 " subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ 380 " jmp .L_do_copy\n" 381 382 ".align 32,0x90\n" 383 ".L_wrap_around_window:\n" 384 " movl 96(%%rsp), %%eax\n" /* eax = write */ 385 " cmpl %%eax, %%ecx\n" 386 " jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ 387 388 " movl 92(%%rsp), %%esi\n" /* from = wsize */ 389 " addq 56(%%rsp), %%rsi\n" /* from += window */ 390 " addq %%rax, %%rsi\n" /* from += write */ 391 " subq %%rcx, %%rsi\n" /* from -= nbytes */ 392 " subl %%eax, %%ecx\n" /* nbytes -= write */ 393 394 " movl %%r14d, %%eax\n" /* eax = len */ 395 " cmpl %%ecx, %%eax\n" 396 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 397 398 " subl %%ecx, %%eax\n" /* len -= nbytes */ 399 " rep movsb\n" 400 " movq 56(%%rsp), %%rsi\n" /* from = window */ 401 " movl 96(%%rsp), %%ecx\n" /* nbytes = write */ 402 " cmpl %%ecx, %%eax\n" 403 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 404 405 " subl %%ecx, %%eax\n" /* len -= nbytes */ 406 " rep movsb\n" 407 " movq %%rdi, %%rsi\n" 408 " subq %%r15, %%rsi\n" /* from = out - dist */ 409 " jmp .L_do_copy\n" 410 411 ".align 32,0x90\n" 412 ".L_contiguous_in_window:\n" 413 " movq 56(%%rsp), %%rsi\n" /* rsi = window */ 414 " addq %%rax, %%rsi\n" 415 " subq %%rcx, %%rsi\n" /* from += write - nbytes */ 416 417 " movl %%r14d, %%eax\n" /* eax = len */ 418 " cmpl %%ecx, %%eax\n" 419 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 420 421 " subl %%ecx, %%eax\n" /* len -= nbytes */ 422 " rep movsb\n" 423 " movq %%rdi, %%rsi\n" 424 " subq %%r15, %%rsi\n" /* from = out - dist */ 425 " jmp .L_do_copy\n" /* if (nbytes >= len) */ 426 427 ".align 32,0x90\n" 428 ".L_do_copy:\n" 429 " movl %%eax, %%ecx\n" /* ecx = len */ 430 " rep movsb\n" 431 432 " movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ 433 " jmp .L_while_test\n" 434 435 ".L_test_for_end_of_block:\n" 436 " testb $32, %%al\n" 437 " jz .L_invalid_literal_length_code\n" 438 " movl $1, 116(%%rsp)\n" 439 " jmp .L_break_loop_with_status\n" 440 441 ".L_invalid_literal_length_code:\n" 442 " movl $2, 116(%%rsp)\n" 443 " jmp .L_break_loop_with_status\n" 444 445 ".L_invalid_distance_code:\n" 446 " movl $3, 116(%%rsp)\n" 447 " jmp .L_break_loop_with_status\n" 448 449 ".L_invalid_distance_too_far:\n" 450 " movl $4, 116(%%rsp)\n" 451 " jmp .L_break_loop_with_status\n" 452 453 ".L_break_loop:\n" 454 " movl $0, 116(%%rsp)\n" 455 456 ".L_break_loop_with_status:\n" 457 /* put in, out, bits, and hold back into ar and pop esp */ 458 " movq %%rsi, 16(%%rsp)\n" /* in */ 459 " movq %%rdi, 32(%%rsp)\n" /* out */ 460 " movl %%ebx, 88(%%rsp)\n" /* bits */ 461 " movq %%rdx, 80(%%rsp)\n" /* hold */ 462 " movq (%%rsp), %%rax\n" /* restore rbp and rsp */ 463 " movq 8(%%rsp), %%rbp\n" 464 " movq %%rax, %%rsp\n" 465 : 466 : "m" (ar) 467 : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", 468 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 469 ); 470 #elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) 471 __asm__ __volatile__ ( 472 " leal %0, %%eax\n" 473 " movl %%esp, (%%eax)\n" /* save esp, ebp */ 474 " movl %%ebp, 4(%%eax)\n" 475 " movl %%eax, %%esp\n" 476 " movl 8(%%esp), %%esi\n" /* esi = in */ 477 " movl 16(%%esp), %%edi\n" /* edi = out */ 478 " movl 40(%%esp), %%edx\n" /* edx = hold */ 479 " movl 44(%%esp), %%ebx\n" /* ebx = bits */ 480 " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ 481 482 " cld\n" 483 " jmp .L_do_loop\n" 484 485 ".align 32,0x90\n" 486 ".L_while_test:\n" 487 " cmpl %%edi, 24(%%esp)\n" /* out < end */ 488 " jbe .L_break_loop\n" 489 " cmpl %%esi, 12(%%esp)\n" /* in < last */ 490 " jbe .L_break_loop\n" 491 492 ".L_do_loop:\n" 493 " cmpb $15, %%bl\n" 494 " ja .L_get_length_code\n" /* if (15 < bits) */ 495 496 " xorl %%eax, %%eax\n" 497 " lodsw\n" /* al = *(ushort *)in++ */ 498 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 499 " addb $16, %%bl\n" /* bits += 16 */ 500 " shll %%cl, %%eax\n" 501 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ 502 503 ".L_get_length_code:\n" 504 " movl 56(%%esp), %%eax\n" /* eax = lmask */ 505 " andl %%edx, %%eax\n" /* eax &= hold */ 506 " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ 507 508 ".L_dolen:\n" 509 " movb %%ah, %%cl\n" /* cl = this.bits */ 510 " subb %%ah, %%bl\n" /* bits -= this.bits */ 511 " shrl %%cl, %%edx\n" /* hold >>= this.bits */ 512 513 " testb %%al, %%al\n" 514 " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ 515 516 " shrl $16, %%eax\n" /* output this.val char */ 517 " stosb\n" 518 " jmp .L_while_test\n" 519 520 ".align 32,0x90\n" 521 ".L_test_for_length_base:\n" 522 " movl %%eax, %%ecx\n" /* len = this */ 523 " shrl $16, %%ecx\n" /* len = this.val */ 524 " movl %%ecx, 64(%%esp)\n" /* save len */ 525 " movb %%al, %%cl\n" 526 527 " testb $16, %%al\n" 528 " jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ 529 " andb $15, %%cl\n" /* op &= 15 */ 530 " jz .L_decode_distance\n" /* if (!op) */ 531 " cmpb %%cl, %%bl\n" 532 " jae .L_add_bits_to_len\n" /* if (op <= bits) */ 533 534 " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ 535 " xorl %%eax, %%eax\n" 536 " lodsw\n" /* al = *(ushort *)in++ */ 537 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 538 " addb $16, %%bl\n" /* bits += 16 */ 539 " shll %%cl, %%eax\n" 540 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ 541 " movb %%ch, %%cl\n" /* move op back to ecx */ 542 543 ".L_add_bits_to_len:\n" 544 " subb %%cl, %%bl\n" 545 " xorl %%eax, %%eax\n" 546 " incl %%eax\n" 547 " shll %%cl, %%eax\n" 548 " decl %%eax\n" 549 " andl %%edx, %%eax\n" /* eax &= hold */ 550 " shrl %%cl, %%edx\n" 551 " addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ 552 553 ".L_decode_distance:\n" 554 " cmpb $15, %%bl\n" 555 " ja .L_get_distance_code\n" /* if (15 < bits) */ 556 557 " xorl %%eax, %%eax\n" 558 " lodsw\n" /* al = *(ushort *)in++ */ 559 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 560 " addb $16, %%bl\n" /* bits += 16 */ 561 " shll %%cl, %%eax\n" 562 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ 563 564 ".L_get_distance_code:\n" 565 " movl 60(%%esp), %%eax\n" /* eax = dmask */ 566 " movl 36(%%esp), %%ecx\n" /* ecx = dcode */ 567 " andl %%edx, %%eax\n" /* eax &= hold */ 568 " movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ 569 570 ".L_dodist:\n" 571 " movl %%eax, %%ebp\n" /* dist = this */ 572 " shrl $16, %%ebp\n" /* dist = this.val */ 573 " movb %%ah, %%cl\n" 574 " subb %%ah, %%bl\n" /* bits -= this.bits */ 575 " shrl %%cl, %%edx\n" /* hold >>= this.bits */ 576 " movb %%al, %%cl\n" /* cl = this.op */ 577 578 " testb $16, %%al\n" /* if ((op & 16) == 0) */ 579 " jz .L_test_for_second_level_dist\n" 580 " andb $15, %%cl\n" /* op &= 15 */ 581 " jz .L_check_dist_one\n" 582 " cmpb %%cl, %%bl\n" 583 " jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ 584 585 " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ 586 " xorl %%eax, %%eax\n" 587 " lodsw\n" /* al = *(ushort *)in++ */ 588 " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ 589 " addb $16, %%bl\n" /* bits += 16 */ 590 " shll %%cl, %%eax\n" 591 " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ 592 " movb %%ch, %%cl\n" /* move op back to ecx */ 593 594 ".L_add_bits_to_dist:\n" 595 " subb %%cl, %%bl\n" 596 " xorl %%eax, %%eax\n" 597 " incl %%eax\n" 598 " shll %%cl, %%eax\n" 599 " decl %%eax\n" /* (1 << op) - 1 */ 600 " andl %%edx, %%eax\n" /* eax &= hold */ 601 " shrl %%cl, %%edx\n" 602 " addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ 603 604 ".L_check_window:\n" 605 " movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ 606 " movl %%edi, %%eax\n" 607 " subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ 608 609 " cmpl %%ebp, %%eax\n" 610 " jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ 611 612 " movl 64(%%esp), %%ecx\n" /* ecx = len */ 613 " movl %%edi, %%esi\n" 614 " subl %%ebp, %%esi\n" /* from = out - dist */ 615 616 " sarl %%ecx\n" 617 " jnc .L_copy_two\n" /* if len % 2 == 0 */ 618 619 " rep movsw\n" 620 " movb (%%esi), %%al\n" 621 " movb %%al, (%%edi)\n" 622 " incl %%edi\n" 623 624 " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ 625 " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ 626 " jmp .L_while_test\n" 627 628 ".L_copy_two:\n" 629 " rep movsw\n" 630 " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ 631 " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ 632 " jmp .L_while_test\n" 633 634 ".align 32,0x90\n" 635 ".L_check_dist_one:\n" 636 " cmpl $1, %%ebp\n" /* if dist 1, is a memset */ 637 " jne .L_check_window\n" 638 " cmpl %%edi, 20(%%esp)\n" 639 " je .L_check_window\n" /* out == beg, if outside window */ 640 641 " movl 64(%%esp), %%ecx\n" /* ecx = len */ 642 " movb -1(%%edi), %%al\n" 643 " movb %%al, %%ah\n" 644 645 " sarl %%ecx\n" 646 " jnc .L_set_two\n" 647 " movb %%al, (%%edi)\n" 648 " incl %%edi\n" 649 650 ".L_set_two:\n" 651 " rep stosw\n" 652 " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ 653 " jmp .L_while_test\n" 654 655 ".align 32,0x90\n" 656 ".L_test_for_second_level_length:\n" 657 " testb $64, %%al\n" 658 " jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ 659 660 " xorl %%eax, %%eax\n" 661 " incl %%eax\n" 662 " shll %%cl, %%eax\n" 663 " decl %%eax\n" 664 " andl %%edx, %%eax\n" /* eax &= hold */ 665 " addl 64(%%esp), %%eax\n" /* eax += len */ 666 " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ 667 " jmp .L_dolen\n" 668 669 ".align 32,0x90\n" 670 ".L_test_for_second_level_dist:\n" 671 " testb $64, %%al\n" 672 " jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ 673 674 " xorl %%eax, %%eax\n" 675 " incl %%eax\n" 676 " shll %%cl, %%eax\n" 677 " decl %%eax\n" 678 " andl %%edx, %%eax\n" /* eax &= hold */ 679 " addl %%ebp, %%eax\n" /* eax += dist */ 680 " movl 36(%%esp), %%ecx\n" /* ecx = dcode */ 681 " movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ 682 " jmp .L_dodist\n" 683 684 ".align 32,0x90\n" 685 ".L_clip_window:\n" 686 " movl %%eax, %%ecx\n" 687 " movl 48(%%esp), %%eax\n" /* eax = wsize */ 688 " negl %%ecx\n" /* nbytes = -nbytes */ 689 " movl 28(%%esp), %%esi\n" /* from = window */ 690 691 " cmpl %%ebp, %%eax\n" 692 " jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ 693 694 " addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ 695 " cmpl $0, 52(%%esp)\n" 696 " jne .L_wrap_around_window\n" /* if (write != 0) */ 697 698 " subl %%ecx, %%eax\n" 699 " addl %%eax, %%esi\n" /* from += wsize - nbytes */ 700 701 " movl 64(%%esp), %%eax\n" /* eax = len */ 702 " cmpl %%ecx, %%eax\n" 703 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 704 705 " subl %%ecx, %%eax\n" /* len -= nbytes */ 706 " rep movsb\n" 707 " movl %%edi, %%esi\n" 708 " subl %%ebp, %%esi\n" /* from = out - dist */ 709 " jmp .L_do_copy\n" 710 711 ".align 32,0x90\n" 712 ".L_wrap_around_window:\n" 713 " movl 52(%%esp), %%eax\n" /* eax = write */ 714 " cmpl %%eax, %%ecx\n" 715 " jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ 716 717 " addl 48(%%esp), %%esi\n" /* from += wsize */ 718 " addl %%eax, %%esi\n" /* from += write */ 719 " subl %%ecx, %%esi\n" /* from -= nbytes */ 720 " subl %%eax, %%ecx\n" /* nbytes -= write */ 721 722 " movl 64(%%esp), %%eax\n" /* eax = len */ 723 " cmpl %%ecx, %%eax\n" 724 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 725 726 " subl %%ecx, %%eax\n" /* len -= nbytes */ 727 " rep movsb\n" 728 " movl 28(%%esp), %%esi\n" /* from = window */ 729 " movl 52(%%esp), %%ecx\n" /* nbytes = write */ 730 " cmpl %%ecx, %%eax\n" 731 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 732 733 " subl %%ecx, %%eax\n" /* len -= nbytes */ 734 " rep movsb\n" 735 " movl %%edi, %%esi\n" 736 " subl %%ebp, %%esi\n" /* from = out - dist */ 737 " jmp .L_do_copy\n" 738 739 ".align 32,0x90\n" 740 ".L_contiguous_in_window:\n" 741 " addl %%eax, %%esi\n" 742 " subl %%ecx, %%esi\n" /* from += write - nbytes */ 743 744 " movl 64(%%esp), %%eax\n" /* eax = len */ 745 " cmpl %%ecx, %%eax\n" 746 " jbe .L_do_copy\n" /* if (nbytes >= len) */ 747 748 " subl %%ecx, %%eax\n" /* len -= nbytes */ 749 " rep movsb\n" 750 " movl %%edi, %%esi\n" 751 " subl %%ebp, %%esi\n" /* from = out - dist */ 752 " jmp .L_do_copy\n" /* if (nbytes >= len) */ 753 754 ".align 32,0x90\n" 755 ".L_do_copy:\n" 756 " movl %%eax, %%ecx\n" 757 " rep movsb\n" 758 759 " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ 760 " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ 761 " jmp .L_while_test\n" 762 763 ".L_test_for_end_of_block:\n" 764 " testb $32, %%al\n" 765 " jz .L_invalid_literal_length_code\n" 766 " movl $1, 72(%%esp)\n" 767 " jmp .L_break_loop_with_status\n" 768 769 ".L_invalid_literal_length_code:\n" 770 " movl $2, 72(%%esp)\n" 771 " jmp .L_break_loop_with_status\n" 772 773 ".L_invalid_distance_code:\n" 774 " movl $3, 72(%%esp)\n" 775 " jmp .L_break_loop_with_status\n" 776 777 ".L_invalid_distance_too_far:\n" 778 " movl 8(%%esp), %%esi\n" 779 " movl $4, 72(%%esp)\n" 780 " jmp .L_break_loop_with_status\n" 781 782 ".L_break_loop:\n" 783 " movl $0, 72(%%esp)\n" 784 785 ".L_break_loop_with_status:\n" 786 /* put in, out, bits, and hold back into ar and pop esp */ 787 " movl %%esi, 8(%%esp)\n" /* save in */ 788 " movl %%edi, 16(%%esp)\n" /* save out */ 789 " movl %%ebx, 44(%%esp)\n" /* save bits */ 790 " movl %%edx, 40(%%esp)\n" /* save hold */ 791 " movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ 792 " movl (%%esp), %%esp\n" 793 : 794 : "m" (ar) 795 : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" 796 ); 797 #elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) 798 __asm { 799 lea eax, ar 800 mov [eax], esp /* save esp, ebp */ 801 mov [eax+4], ebp 802 mov esp, eax 803 mov esi, [esp+8] /* esi = in */ 804 mov edi, [esp+16] /* edi = out */ 805 mov edx, [esp+40] /* edx = hold */ 806 mov ebx, [esp+44] /* ebx = bits */ 807 mov ebp, [esp+32] /* ebp = lcode */ 808 809 cld 810 jmp L_do_loop 811 812 ALIGN 4 813 L_while_test: 814 cmp [esp+24], edi 815 jbe L_break_loop 816 cmp [esp+12], esi 817 jbe L_break_loop 818 819 L_do_loop: 820 cmp bl, 15 821 ja L_get_length_code /* if (15 < bits) */ 822 823 xor eax, eax 824 lodsw /* al = *(ushort *)in++ */ 825 mov cl, bl /* cl = bits, needs it for shifting */ 826 add bl, 16 /* bits += 16 */ 827 shl eax, cl 828 or edx, eax /* hold |= *((ushort *)in)++ << bits */ 829 830 L_get_length_code: 831 mov eax, [esp+56] /* eax = lmask */ 832 and eax, edx /* eax &= hold */ 833 mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ 834 835 L_dolen: 836 mov cl, ah /* cl = this.bits */ 837 sub bl, ah /* bits -= this.bits */ 838 shr edx, cl /* hold >>= this.bits */ 839 840 test al, al 841 jnz L_test_for_length_base /* if (op != 0) 45.7% */ 842 843 shr eax, 16 /* output this.val char */ 844 stosb 845 jmp L_while_test 846 847 ALIGN 4 848 L_test_for_length_base: 849 mov ecx, eax /* len = this */ 850 shr ecx, 16 /* len = this.val */ 851 mov [esp+64], ecx /* save len */ 852 mov cl, al 853 854 test al, 16 855 jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ 856 and cl, 15 /* op &= 15 */ 857 jz L_decode_distance /* if (!op) */ 858 cmp bl, cl 859 jae L_add_bits_to_len /* if (op <= bits) */ 860 861 mov ch, cl /* stash op in ch, freeing cl */ 862 xor eax, eax 863 lodsw /* al = *(ushort *)in++ */ 864 mov cl, bl /* cl = bits, needs it for shifting */ 865 add bl, 16 /* bits += 16 */ 866 shl eax, cl 867 or edx, eax /* hold |= *((ushort *)in)++ << bits */ 868 mov cl, ch /* move op back to ecx */ 869 870 L_add_bits_to_len: 871 sub bl, cl 872 xor eax, eax 873 inc eax 874 shl eax, cl 875 dec eax 876 and eax, edx /* eax &= hold */ 877 shr edx, cl 878 add [esp+64], eax /* len += hold & mask[op] */ 879 880 L_decode_distance: 881 cmp bl, 15 882 ja L_get_distance_code /* if (15 < bits) */ 883 884 xor eax, eax 885 lodsw /* al = *(ushort *)in++ */ 886 mov cl, bl /* cl = bits, needs it for shifting */ 887 add bl, 16 /* bits += 16 */ 888 shl eax, cl 889 or edx, eax /* hold |= *((ushort *)in)++ << bits */ 890 891 L_get_distance_code: 892 mov eax, [esp+60] /* eax = dmask */ 893 mov ecx, [esp+36] /* ecx = dcode */ 894 and eax, edx /* eax &= hold */ 895 mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ 896 897 L_dodist: 898 mov ebp, eax /* dist = this */ 899 shr ebp, 16 /* dist = this.val */ 900 mov cl, ah 901 sub bl, ah /* bits -= this.bits */ 902 shr edx, cl /* hold >>= this.bits */ 903 mov cl, al /* cl = this.op */ 904 905 test al, 16 /* if ((op & 16) == 0) */ 906 jz L_test_for_second_level_dist 907 and cl, 15 /* op &= 15 */ 908 jz L_check_dist_one 909 cmp bl, cl 910 jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ 911 912 mov ch, cl /* stash op in ch, freeing cl */ 913 xor eax, eax 914 lodsw /* al = *(ushort *)in++ */ 915 mov cl, bl /* cl = bits, needs it for shifting */ 916 add bl, 16 /* bits += 16 */ 917 shl eax, cl 918 or edx, eax /* hold |= *((ushort *)in)++ << bits */ 919 mov cl, ch /* move op back to ecx */ 920 921 L_add_bits_to_dist: 922 sub bl, cl 923 xor eax, eax 924 inc eax 925 shl eax, cl 926 dec eax /* (1 << op) - 1 */ 927 and eax, edx /* eax &= hold */ 928 shr edx, cl 929 add ebp, eax /* dist += hold & ((1 << op) - 1) */ 930 931 L_check_window: 932 mov [esp+8], esi /* save in so from can use it's reg */ 933 mov eax, edi 934 sub eax, [esp+20] /* nbytes = out - beg */ 935 936 cmp eax, ebp 937 jb L_clip_window /* if (dist > nbytes) 4.2% */ 938 939 mov ecx, [esp+64] /* ecx = len */ 940 mov esi, edi 941 sub esi, ebp /* from = out - dist */ 942 943 sar ecx, 1 944 jnc L_copy_two 945 946 rep movsw 947 mov al, [esi] 948 mov [edi], al 949 inc edi 950 951 mov esi, [esp+8] /* move in back to %esi, toss from */ 952 mov ebp, [esp+32] /* ebp = lcode */ 953 jmp L_while_test 954 955 L_copy_two: 956 rep movsw 957 mov esi, [esp+8] /* move in back to %esi, toss from */ 958 mov ebp, [esp+32] /* ebp = lcode */ 959 jmp L_while_test 960 961 ALIGN 4 962 L_check_dist_one: 963 cmp ebp, 1 /* if dist 1, is a memset */ 964 jne L_check_window 965 cmp [esp+20], edi 966 je L_check_window /* out == beg, if outside window */ 967 968 mov ecx, [esp+64] /* ecx = len */ 969 mov al, [edi-1] 970 mov ah, al 971 972 sar ecx, 1 973 jnc L_set_two 974 mov [edi], al /* memset out with from[-1] */ 975 inc edi 976 977 L_set_two: 978 rep stosw 979 mov ebp, [esp+32] /* ebp = lcode */ 980 jmp L_while_test 981 982 ALIGN 4 983 L_test_for_second_level_length: 984 test al, 64 985 jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ 986 987 xor eax, eax 988 inc eax 989 shl eax, cl 990 dec eax 991 and eax, edx /* eax &= hold */ 992 add eax, [esp+64] /* eax += len */ 993 mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ 994 jmp L_dolen 995 996 ALIGN 4 997 L_test_for_second_level_dist: 998 test al, 64 999 jnz L_invalid_distance_code /* if ((op & 64) != 0) */ 1000 1001 xor eax, eax 1002 inc eax 1003 shl eax, cl 1004 dec eax 1005 and eax, edx /* eax &= hold */ 1006 add eax, ebp /* eax += dist */ 1007 mov ecx, [esp+36] /* ecx = dcode */ 1008 mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ 1009 jmp L_dodist 1010 1011 ALIGN 4 1012 L_clip_window: 1013 mov ecx, eax 1014 mov eax, [esp+48] /* eax = wsize */ 1015 neg ecx /* nbytes = -nbytes */ 1016 mov esi, [esp+28] /* from = window */ 1017 1018 cmp eax, ebp 1019 jb L_invalid_distance_too_far /* if (dist > wsize) */ 1020 1021 add ecx, ebp /* nbytes = dist - nbytes */ 1022 cmp dword ptr [esp+52], 0 1023 jne L_wrap_around_window /* if (write != 0) */ 1024 1025 sub eax, ecx 1026 add esi, eax /* from += wsize - nbytes */ 1027 1028 mov eax, [esp+64] /* eax = len */ 1029 cmp eax, ecx 1030 jbe L_do_copy /* if (nbytes >= len) */ 1031 1032 sub eax, ecx /* len -= nbytes */ 1033 rep movsb 1034 mov esi, edi 1035 sub esi, ebp /* from = out - dist */ 1036 jmp L_do_copy 1037 1038 ALIGN 4 1039 L_wrap_around_window: 1040 mov eax, [esp+52] /* eax = write */ 1041 cmp ecx, eax 1042 jbe L_contiguous_in_window /* if (write >= nbytes) */ 1043 1044 add esi, [esp+48] /* from += wsize */ 1045 add esi, eax /* from += write */ 1046 sub esi, ecx /* from -= nbytes */ 1047 sub ecx, eax /* nbytes -= write */ 1048 1049 mov eax, [esp+64] /* eax = len */ 1050 cmp eax, ecx 1051 jbe L_do_copy /* if (nbytes >= len) */ 1052 1053 sub eax, ecx /* len -= nbytes */ 1054 rep movsb 1055 mov esi, [esp+28] /* from = window */ 1056 mov ecx, [esp+52] /* nbytes = write */ 1057 cmp eax, ecx 1058 jbe L_do_copy /* if (nbytes >= len) */ 1059 1060 sub eax, ecx /* len -= nbytes */ 1061 rep movsb 1062 mov esi, edi 1063 sub esi, ebp /* from = out - dist */ 1064 jmp L_do_copy 1065 1066 ALIGN 4 1067 L_contiguous_in_window: 1068 add esi, eax 1069 sub esi, ecx /* from += write - nbytes */ 1070 1071 mov eax, [esp+64] /* eax = len */ 1072 cmp eax, ecx 1073 jbe L_do_copy /* if (nbytes >= len) */ 1074 1075 sub eax, ecx /* len -= nbytes */ 1076 rep movsb 1077 mov esi, edi 1078 sub esi, ebp /* from = out - dist */ 1079 jmp L_do_copy 1080 1081 ALIGN 4 1082 L_do_copy: 1083 mov ecx, eax 1084 rep movsb 1085 1086 mov esi, [esp+8] /* move in back to %esi, toss from */ 1087 mov ebp, [esp+32] /* ebp = lcode */ 1088 jmp L_while_test 1089 1090 L_test_for_end_of_block: 1091 test al, 32 1092 jz L_invalid_literal_length_code 1093 mov dword ptr [esp+72], 1 1094 jmp L_break_loop_with_status 1095 1096 L_invalid_literal_length_code: 1097 mov dword ptr [esp+72], 2 1098 jmp L_break_loop_with_status 1099 1100 L_invalid_distance_code: 1101 mov dword ptr [esp+72], 3 1102 jmp L_break_loop_with_status 1103 1104 L_invalid_distance_too_far: 1105 mov esi, [esp+4] 1106 mov dword ptr [esp+72], 4 1107 jmp L_break_loop_with_status 1108 1109 L_break_loop: 1110 mov dword ptr [esp+72], 0 1111 1112 L_break_loop_with_status: 1113 /* put in, out, bits, and hold back into ar and pop esp */ 1114 mov [esp+8], esi /* save in */ 1115 mov [esp+16], edi /* save out */ 1116 mov [esp+44], ebx /* save bits */ 1117 mov [esp+40], edx /* save hold */ 1118 mov ebp, [esp+4] /* restore esp, ebp */ 1119 mov esp, [esp] 1120 } 1121 #else 1122 #error "x86 architecture not defined" 1123 #endif 1124 1125 if (ar.status > 1) { 1126 if (ar.status == 2) 1127 strm->msg = "invalid literal/length code"; 1128 else if (ar.status == 3) 1129 strm->msg = "invalid distance code"; 1130 else 1131 strm->msg = "invalid distance too far back"; 1132 state->mode = BAD; 1133 } 1134 else if ( ar.status == 1 ) { 1135 state->mode = TYPE; 1136 } 1137 1138 /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ 1139 ar.len = ar.bits >> 3; 1140 ar.in -= ar.len; 1141 ar.bits -= ar.len << 3; 1142 ar.hold &= (1U << ar.bits) - 1; 1143 1144 /* update state and return */ 1145 strm->next_in = ar.in; 1146 strm->next_out = ar.out; 1147 strm->avail_in = (unsigned)(ar.in < ar.last ? 1148 PAD_AVAIL_IN + (ar.last - ar.in) : 1149 PAD_AVAIL_IN - (ar.in - ar.last)); 1150 strm->avail_out = (unsigned)(ar.out < ar.end ? 1151 PAD_AVAIL_OUT + (ar.end - ar.out) : 1152 PAD_AVAIL_OUT - (ar.out - ar.end)); 1153 state->hold = ar.hold; 1154 state->bits = ar.bits; 1155 return; 1156 } 1157 1158