kusano fc6ab3
/* inffas86.c is a hand tuned assembler version of
kusano fc6ab3
 *
kusano fc6ab3
 * inffast.c -- fast decoding
kusano fc6ab3
 * Copyright (C) 1995-2003 Mark Adler
kusano fc6ab3
 * For conditions of distribution and use, see copyright notice in zlib.h
kusano fc6ab3
 *
kusano fc6ab3
 * Copyright (C) 2003 Chris Anderson <christop@charm.net></christop@charm.net>
kusano fc6ab3
 * Please use the copyright conditions above.
kusano fc6ab3
 *
kusano fc6ab3
 * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also
kusano fc6ab3
 * slightly quicker on x86 systems because, instead of using rep movsb to copy
kusano fc6ab3
 * data, it uses rep movsw, which moves data in 2-byte chunks instead of single
kusano fc6ab3
 * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
kusano fc6ab3
 * from http://fedora.linux.duke.edu/fc1_x86_64
kusano fc6ab3
 * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
kusano fc6ab3
 * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,
kusano fc6ab3
 * when decompressing mozilla-source-1.3.tar.gz.
kusano fc6ab3
 *
kusano fc6ab3
 * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
kusano fc6ab3
 * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
kusano fc6ab3
 * the moment.  I have successfully compiled and tested this code with gcc2.96,
kusano fc6ab3
 * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
kusano fc6ab3
 * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
kusano fc6ab3
 * enabled.  I will attempt to merge the MMX code into this version.  Newer
kusano fc6ab3
 * versions of this and inffast.S can be found at
kusano fc6ab3
 * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
kusano fc6ab3
 */
kusano fc6ab3
kusano fc6ab3
#include "zutil.h"
kusano fc6ab3
#include "inftrees.h"
kusano fc6ab3
#include "inflate.h"
kusano fc6ab3
#include "inffast.h"
kusano fc6ab3
kusano fc6ab3
/* Mark Adler's comments from inffast.c: */
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   Decode literal, length, and distance codes and write out the resulting
kusano fc6ab3
   literal and match bytes until either not enough input or output is
kusano fc6ab3
   available, an end-of-block is encountered, or a data error is encountered.
kusano fc6ab3
   When large enough input and output buffers are supplied to inflate(), for
kusano fc6ab3
   example, a 16K input buffer and a 64K output buffer, more than 95% of the
kusano fc6ab3
   inflate execution time is spent in this routine.
kusano fc6ab3
kusano fc6ab3
   Entry assumptions:
kusano fc6ab3
kusano fc6ab3
        state->mode == LEN
kusano fc6ab3
        strm->avail_in >= 6
kusano fc6ab3
        strm->avail_out >= 258
kusano fc6ab3
        start >= strm->avail_out
kusano fc6ab3
        state->bits < 8
kusano fc6ab3
kusano fc6ab3
   On return, state->mode is one of:
kusano fc6ab3
kusano fc6ab3
        LEN -- ran out of enough output space or enough available input
kusano fc6ab3
        TYPE -- reached end of block code, inflate() to interpret next block
kusano fc6ab3
        BAD -- error in block data
kusano fc6ab3
kusano fc6ab3
   Notes:
kusano fc6ab3
kusano fc6ab3
    - The maximum input bits used by a length/distance pair is 15 bits for the
kusano fc6ab3
      length code, 5 bits for the length extra, 15 bits for the distance code,
kusano fc6ab3
      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
kusano fc6ab3
      Therefore if strm->avail_in >= 6, then there is enough input to avoid
kusano fc6ab3
      checking for available input while decoding.
kusano fc6ab3
kusano fc6ab3
    - The maximum bytes that a single length/distance pair can output is 258
kusano fc6ab3
      bytes, which is the maximum length that can be coded.  inflate_fast()
kusano fc6ab3
      requires strm->avail_out >= 258 for each loop to avoid checking for
kusano fc6ab3
      output space.
kusano fc6ab3
 */
kusano fc6ab3
void inflate_fast(strm, start)
kusano fc6ab3
z_streamp strm;
kusano fc6ab3
unsigned start;         /* inflate()'s starting value for strm->avail_out */
kusano fc6ab3
{
kusano fc6ab3
    struct inflate_state FAR *state;
kusano fc6ab3
    struct inffast_ar {
kusano fc6ab3
/* 64   32                               x86  x86_64 */
kusano fc6ab3
/* ar offset                              register */
kusano fc6ab3
/*  0    0 */ void *esp;                /* esp save */
kusano fc6ab3
/*  8    4 */ void *ebp;                /* ebp save */
kusano fc6ab3
/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
kusano fc6ab3
/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
kusano fc6ab3
/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
kusano fc6ab3
/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
kusano fc6ab3
/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
kusano fc6ab3
/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
kusano fc6ab3
/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
kusano fc6ab3
/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
kusano fc6ab3
/* 80   40 */ unsigned long hold;       /* edx rdx  local strm->hold */
kusano fc6ab3
/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
kusano fc6ab3
/* 92   48 */ unsigned wsize;           /*          window size */
kusano fc6ab3
/* 96   52 */ unsigned write;           /*          window write index */
kusano fc6ab3
/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
kusano fc6ab3
/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
kusano fc6ab3
/*108   64 */ unsigned len;             /*     r14  match length */
kusano fc6ab3
/*112   68 */ unsigned dist;            /*     r15  match distance */
kusano fc6ab3
/*116   72 */ unsigned status;          /*          set when state chng*/
kusano fc6ab3
    } ar;
kusano fc6ab3
kusano fc6ab3
#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
kusano fc6ab3
#define PAD_AVAIL_IN 6
kusano fc6ab3
#define PAD_AVAIL_OUT 258
kusano fc6ab3
#else
kusano fc6ab3
#define PAD_AVAIL_IN 5
kusano fc6ab3
#define PAD_AVAIL_OUT 257
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
    /* copy state to local variables */
kusano fc6ab3
    state = (struct inflate_state FAR *)strm->state;
kusano fc6ab3
    ar.in = strm->next_in;
kusano fc6ab3
    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
kusano fc6ab3
    ar.out = strm->next_out;
kusano fc6ab3
    ar.beg = ar.out - (start - strm->avail_out);
kusano fc6ab3
    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
kusano fc6ab3
    ar.wsize = state->wsize;
kusano fc6ab3
    ar.write = state->wnext;
kusano fc6ab3
    ar.window = state->window;
kusano fc6ab3
    ar.hold = state->hold;
kusano fc6ab3
    ar.bits = state->bits;
kusano fc6ab3
    ar.lcode = state->lencode;
kusano fc6ab3
    ar.dcode = state->distcode;
kusano fc6ab3
    ar.lmask = (1U << state->lenbits) - 1;
kusano fc6ab3
    ar.dmask = (1U << state->distbits) - 1;
kusano fc6ab3
kusano fc6ab3
    /* decode literals and length/distances until end-of-block or not enough
kusano fc6ab3
       input data or output space */
kusano fc6ab3
kusano fc6ab3
    /* align in on 1/2 hold size boundary */
kusano fc6ab3
    while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
kusano fc6ab3
        ar.hold += (unsigned long)*ar.in++ << ar.bits;
kusano fc6ab3
        ar.bits += 8;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
kusano fc6ab3
    __asm__ __volatile__ (
kusano fc6ab3
"        leaq    %0, %%rax\n"
kusano fc6ab3
"        movq    %%rbp, 8(%%rax)\n"       /* save regs rbp and rsp */
kusano fc6ab3
"        movq    %%rsp, (%%rax)\n"
kusano fc6ab3
"        movq    %%rax, %%rsp\n"          /* make rsp point to &ar */
kusano fc6ab3
"        movq    16(%%rsp), %%rsi\n"      /* rsi  = in */
kusano fc6ab3
"        movq    32(%%rsp), %%rdi\n"      /* rdi  = out */
kusano fc6ab3
"        movq    24(%%rsp), %%r9\n"       /* r9   = last */
kusano fc6ab3
"        movq    48(%%rsp), %%r10\n"      /* r10  = end */
kusano fc6ab3
"        movq    64(%%rsp), %%rbp\n"      /* rbp  = lcode */
kusano fc6ab3
"        movq    72(%%rsp), %%r11\n"      /* r11  = dcode */
kusano fc6ab3
"        movq    80(%%rsp), %%rdx\n"      /* rdx  = hold */
kusano fc6ab3
"        movl    88(%%rsp), %%ebx\n"      /* ebx  = bits */
kusano fc6ab3
"        movl    100(%%rsp), %%r12d\n"    /* r12d = lmask */
kusano fc6ab3
"        movl    104(%%rsp), %%r13d\n"    /* r13d = dmask */
kusano fc6ab3
                                          /* r14d = len */
kusano fc6ab3
                                          /* r15d = dist */
kusano fc6ab3
"        cld\n"
kusano fc6ab3
"        cmpq    %%rdi, %%r10\n"
kusano fc6ab3
"        je      .L_one_time\n"           /* if only one decode left */
kusano fc6ab3
"        cmpq    %%rsi, %%r9\n"
kusano fc6ab3
"        je      .L_one_time\n"
kusano fc6ab3
"        jmp     .L_do_loop\n"
kusano fc6ab3
kusano fc6ab3
".L_one_time:\n"
kusano fc6ab3
"        movq    %%r12, %%r8\n"           /* r8 = lmask */
kusano fc6ab3
"        cmpb    $32, %%bl\n"
kusano fc6ab3
"        ja      .L_get_length_code_one_time\n"
kusano fc6ab3
kusano fc6ab3
"        lodsl\n"                         /* eax = *(uint *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $32, %%bl\n"             /* bits += 32 */
kusano fc6ab3
"        shlq    %%cl, %%rax\n"
kusano fc6ab3
"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
kusano fc6ab3
"        jmp     .L_get_length_code_one_time\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_while_test:\n"
kusano fc6ab3
"        cmpq    %%rdi, %%r10\n"
kusano fc6ab3
"        jbe     .L_break_loop\n"
kusano fc6ab3
"        cmpq    %%rsi, %%r9\n"
kusano fc6ab3
"        jbe     .L_break_loop\n"
kusano fc6ab3
kusano fc6ab3
".L_do_loop:\n"
kusano fc6ab3
"        movq    %%r12, %%r8\n"           /* r8 = lmask */
kusano fc6ab3
"        cmpb    $32, %%bl\n"
kusano fc6ab3
"        ja      .L_get_length_code\n"    /* if (32 < bits) */
kusano fc6ab3
kusano fc6ab3
"        lodsl\n"                         /* eax = *(uint *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $32, %%bl\n"             /* bits += 32 */
kusano fc6ab3
"        shlq    %%cl, %%rax\n"
kusano fc6ab3
"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
".L_get_length_code:\n"
kusano fc6ab3
"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
kusano fc6ab3
"        movl    (%%rbp,%%r8,4), %%eax\n"  /* eax = lcode[hold & lmask] */
kusano fc6ab3
kusano fc6ab3
"        movb    %%ah, %%cl\n"            /* cl = this.bits */
kusano fc6ab3
"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
kusano fc6ab3
"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
kusano fc6ab3
kusano fc6ab3
"        testb   %%al, %%al\n"
kusano fc6ab3
"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
kusano fc6ab3
kusano fc6ab3
"        movq    %%r12, %%r8\n"            /* r8 = lmask */
kusano fc6ab3
"        shrl    $16, %%eax\n"            /* output this.val char */
kusano fc6ab3
"        stosb\n"
kusano fc6ab3
kusano fc6ab3
".L_get_length_code_one_time:\n"
kusano fc6ab3
"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
kusano fc6ab3
"        movl    (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */
kusano fc6ab3
kusano fc6ab3
".L_dolen:\n"
kusano fc6ab3
"        movb    %%ah, %%cl\n"            /* cl = this.bits */
kusano fc6ab3
"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
kusano fc6ab3
"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
kusano fc6ab3
kusano fc6ab3
"        testb   %%al, %%al\n"
kusano fc6ab3
"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
kusano fc6ab3
kusano fc6ab3
"        shrl    $16, %%eax\n"            /* output this.val char */
kusano fc6ab3
"        stosb\n"
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_length_base:\n"
kusano fc6ab3
"        movl    %%eax, %%r14d\n"         /* len = this */
kusano fc6ab3
"        shrl    $16, %%r14d\n"           /* len = this.val */
kusano fc6ab3
"        movb    %%al, %%cl\n"
kusano fc6ab3
kusano fc6ab3
"        testb   $16, %%al\n"
kusano fc6ab3
"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
kusano fc6ab3
"        andb    $15, %%cl\n"             /* op &= 15 */
kusano fc6ab3
"        jz      .L_decode_distance\n"    /* if (!op) */
kusano fc6ab3
kusano fc6ab3
".L_add_bits_to_len:\n"
kusano fc6ab3
"        subb    %%cl, %%bl\n"
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        shrq    %%cl, %%rdx\n"
kusano fc6ab3
"        addl    %%eax, %%r14d\n"         /* len += hold & mask[op] */
kusano fc6ab3
kusano fc6ab3
".L_decode_distance:\n"
kusano fc6ab3
"        movq    %%r13, %%r8\n"           /* r8 = dmask */
kusano fc6ab3
"        cmpb    $32, %%bl\n"
kusano fc6ab3
"        ja      .L_get_distance_code\n"  /* if (32 < bits) */
kusano fc6ab3
kusano fc6ab3
"        lodsl\n"                         /* eax = *(uint *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $32, %%bl\n"             /* bits += 32 */
kusano fc6ab3
"        shlq    %%cl, %%rax\n"
kusano fc6ab3
"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
".L_get_distance_code:\n"
kusano fc6ab3
"        andq    %%rdx, %%r8\n"           /* r8 &= hold */
kusano fc6ab3
"        movl    (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */
kusano fc6ab3
kusano fc6ab3
".L_dodist:\n"
kusano fc6ab3
"        movl    %%eax, %%r15d\n"         /* dist = this */
kusano fc6ab3
"        shrl    $16, %%r15d\n"           /* dist = this.val */
kusano fc6ab3
"        movb    %%ah, %%cl\n"
kusano fc6ab3
"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
kusano fc6ab3
"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
kusano fc6ab3
"        movb    %%al, %%cl\n"            /* cl = this.op */
kusano fc6ab3
kusano fc6ab3
"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
kusano fc6ab3
"        jz      .L_test_for_second_level_dist\n"
kusano fc6ab3
"        andb    $15, %%cl\n"             /* op &= 15 */
kusano fc6ab3
"        jz      .L_check_dist_one\n"
kusano fc6ab3
kusano fc6ab3
".L_add_bits_to_dist:\n"
kusano fc6ab3
"        subb    %%cl, %%bl\n"
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"                 /* (1 << op) - 1 */
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        shrq    %%cl, %%rdx\n"
kusano fc6ab3
"        addl    %%eax, %%r15d\n"         /* dist += hold & ((1 << op) - 1) */
kusano fc6ab3
kusano fc6ab3
".L_check_window:\n"
kusano fc6ab3
"        movq    %%rsi, %%r8\n"           /* save in so from can use it's reg */
kusano fc6ab3
"        movq    %%rdi, %%rax\n"
kusano fc6ab3
"        subq    40(%%rsp), %%rax\n"      /* nbytes = out - beg */
kusano fc6ab3
kusano fc6ab3
"        cmpl    %%r15d, %%eax\n"
kusano fc6ab3
"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
kusano fc6ab3
kusano fc6ab3
"        movl    %%r14d, %%ecx\n"         /* ecx = len */
kusano fc6ab3
"        movq    %%rdi, %%rsi\n"
kusano fc6ab3
"        subq    %%r15, %%rsi\n"          /* from = out - dist */
kusano fc6ab3
kusano fc6ab3
"        sarl    %%ecx\n"
kusano fc6ab3
"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
kusano fc6ab3
kusano fc6ab3
"        rep     movsw\n"
kusano fc6ab3
"        movb    (%%rsi), %%al\n"
kusano fc6ab3
"        movb    %%al, (%%rdi)\n"
kusano fc6ab3
"        incq    %%rdi\n"
kusano fc6ab3
kusano fc6ab3
"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".L_copy_two:\n"
kusano fc6ab3
"        rep     movsw\n"
kusano fc6ab3
"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_check_dist_one:\n"
kusano fc6ab3
"        cmpl    $1, %%r15d\n"            /* if dist 1, is a memset */
kusano fc6ab3
"        jne     .L_check_window\n"
kusano fc6ab3
"        cmpq    %%rdi, 40(%%rsp)\n"      /* if out == beg, outside window */
kusano fc6ab3
"        je      .L_check_window\n"
kusano fc6ab3
kusano fc6ab3
"        movl    %%r14d, %%ecx\n"         /* ecx = len */
kusano fc6ab3
"        movb    -1(%%rdi), %%al\n"
kusano fc6ab3
"        movb    %%al, %%ah\n"
kusano fc6ab3
kusano fc6ab3
"        sarl    %%ecx\n"
kusano fc6ab3
"        jnc     .L_set_two\n"
kusano fc6ab3
"        movb    %%al, (%%rdi)\n"
kusano fc6ab3
"        incq    %%rdi\n"
kusano fc6ab3
kusano fc6ab3
".L_set_two:\n"
kusano fc6ab3
"        rep     stosw\n"
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_second_level_length:\n"
kusano fc6ab3
"        testb   $64, %%al\n"
kusano fc6ab3
"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"         /* eax &= hold */
kusano fc6ab3
"        addl    %%r14d, %%eax\n"        /* eax += len */
kusano fc6ab3
"        movl    (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
kusano fc6ab3
"        jmp     .L_dolen\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_second_level_dist:\n"
kusano fc6ab3
"        testb   $64, %%al\n"
kusano fc6ab3
"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"         /* eax &= hold */
kusano fc6ab3
"        addl    %%r15d, %%eax\n"        /* eax += dist */
kusano fc6ab3
"        movl    (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
kusano fc6ab3
"        jmp     .L_dodist\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_clip_window:\n"
kusano fc6ab3
"        movl    %%eax, %%ecx\n"         /* ecx = nbytes */
kusano fc6ab3
"        movl    92(%%rsp), %%eax\n"     /* eax = wsize, prepare for dist cmp */
kusano fc6ab3
"        negl    %%ecx\n"                /* nbytes = -nbytes */
kusano fc6ab3
kusano fc6ab3
"        cmpl    %%r15d, %%eax\n"
kusano fc6ab3
"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
kusano fc6ab3
kusano fc6ab3
"        addl    %%r15d, %%ecx\n"         /* nbytes = dist - nbytes */
kusano fc6ab3
"        cmpl    $0, 96(%%rsp)\n"
kusano fc6ab3
"        jne     .L_wrap_around_window\n" /* if (write != 0) */
kusano fc6ab3
kusano fc6ab3
"        movq    56(%%rsp), %%rsi\n"     /* from  = window */
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* eax  -= nbytes */
kusano fc6ab3
"        addq    %%rax, %%rsi\n"         /* from += wsize - nbytes */
kusano fc6ab3
kusano fc6ab3
"        movl    %%r14d, %%eax\n"        /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%r14d\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* eax -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movq    %%rdi, %%rsi\n"
kusano fc6ab3
"        subq    %%r15, %%rsi\n"         /* from = &out[ -dist ] */
kusano fc6ab3
"        jmp     .L_do_copy\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_wrap_around_window:\n"
kusano fc6ab3
"        movl    96(%%rsp), %%eax\n"     /* eax = write */
kusano fc6ab3
"        cmpl    %%eax, %%ecx\n"
kusano fc6ab3
"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
kusano fc6ab3
kusano fc6ab3
"        movl    92(%%rsp), %%esi\n"     /* from  = wsize */
kusano fc6ab3
"        addq    56(%%rsp), %%rsi\n"     /* from += window */
kusano fc6ab3
"        addq    %%rax, %%rsi\n"         /* from += write */
kusano fc6ab3
"        subq    %%rcx, %%rsi\n"         /* from -= nbytes */
kusano fc6ab3
"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
kusano fc6ab3
kusano fc6ab3
"        movl    %%r14d, %%eax\n"        /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movq    56(%%rsp), %%rsi\n"     /* from = window */
kusano fc6ab3
"        movl    96(%%rsp), %%ecx\n"     /* nbytes = write */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movq    %%rdi, %%rsi\n"
kusano fc6ab3
"        subq    %%r15, %%rsi\n"         /* from = out - dist */
kusano fc6ab3
"        jmp     .L_do_copy\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_contiguous_in_window:\n"
kusano fc6ab3
"        movq    56(%%rsp), %%rsi\n"     /* rsi = window */
kusano fc6ab3
"        addq    %%rax, %%rsi\n"
kusano fc6ab3
"        subq    %%rcx, %%rsi\n"         /* from += write - nbytes */
kusano fc6ab3
kusano fc6ab3
"        movl    %%r14d, %%eax\n"        /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movq    %%rdi, %%rsi\n"
kusano fc6ab3
"        subq    %%r15, %%rsi\n"         /* from = out - dist */
kusano fc6ab3
"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_do_copy:\n"
kusano fc6ab3
"        movl    %%eax, %%ecx\n"         /* ecx = len */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
kusano fc6ab3
"        movq    %%r8, %%rsi\n"          /* move in back to %esi, toss from */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".L_test_for_end_of_block:\n"
kusano fc6ab3
"        testb   $32, %%al\n"
kusano fc6ab3
"        jz      .L_invalid_literal_length_code\n"
kusano fc6ab3
"        movl    $1, 116(%%rsp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_literal_length_code:\n"
kusano fc6ab3
"        movl    $2, 116(%%rsp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_distance_code:\n"
kusano fc6ab3
"        movl    $3, 116(%%rsp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_distance_too_far:\n"
kusano fc6ab3
"        movl    $4, 116(%%rsp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_break_loop:\n"
kusano fc6ab3
"        movl    $0, 116(%%rsp)\n"
kusano fc6ab3
kusano fc6ab3
".L_break_loop_with_status:\n"
kusano fc6ab3
/* put in, out, bits, and hold back into ar and pop esp */
kusano fc6ab3
"        movq    %%rsi, 16(%%rsp)\n"     /* in */
kusano fc6ab3
"        movq    %%rdi, 32(%%rsp)\n"     /* out */
kusano fc6ab3
"        movl    %%ebx, 88(%%rsp)\n"     /* bits */
kusano fc6ab3
"        movq    %%rdx, 80(%%rsp)\n"     /* hold */
kusano fc6ab3
"        movq    (%%rsp), %%rax\n"       /* restore rbp and rsp */
kusano fc6ab3
"        movq    8(%%rsp), %%rbp\n"
kusano fc6ab3
"        movq    %%rax, %%rsp\n"
kusano fc6ab3
          :
kusano fc6ab3
          : "m" (ar)
kusano fc6ab3
          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
kusano fc6ab3
            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
kusano fc6ab3
    );
kusano fc6ab3
#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 )
kusano fc6ab3
    __asm__ __volatile__ (
kusano fc6ab3
"        leal    %0, %%eax\n"
kusano fc6ab3
"        movl    %%esp, (%%eax)\n"        /* save esp, ebp */
kusano fc6ab3
"        movl    %%ebp, 4(%%eax)\n"
kusano fc6ab3
"        movl    %%eax, %%esp\n"
kusano fc6ab3
"        movl    8(%%esp), %%esi\n"       /* esi = in */
kusano fc6ab3
"        movl    16(%%esp), %%edi\n"      /* edi = out */
kusano fc6ab3
"        movl    40(%%esp), %%edx\n"      /* edx = hold */
kusano fc6ab3
"        movl    44(%%esp), %%ebx\n"      /* ebx = bits */
kusano fc6ab3
"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
kusano fc6ab3
kusano fc6ab3
"        cld\n"
kusano fc6ab3
"        jmp     .L_do_loop\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_while_test:\n"
kusano fc6ab3
"        cmpl    %%edi, 24(%%esp)\n"      /* out < end */
kusano fc6ab3
"        jbe     .L_break_loop\n"
kusano fc6ab3
"        cmpl    %%esi, 12(%%esp)\n"      /* in < last */
kusano fc6ab3
"        jbe     .L_break_loop\n"
kusano fc6ab3
kusano fc6ab3
".L_do_loop:\n"
kusano fc6ab3
"        cmpb    $15, %%bl\n"
kusano fc6ab3
"        ja      .L_get_length_code\n"    /* if (15 < bits) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        lodsw\n"                         /* al = *(ushort *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $16, %%bl\n"             /* bits += 16 */
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
".L_get_length_code:\n"
kusano fc6ab3
"        movl    56(%%esp), %%eax\n"      /* eax = lmask */
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */
kusano fc6ab3
kusano fc6ab3
".L_dolen:\n"
kusano fc6ab3
"        movb    %%ah, %%cl\n"            /* cl = this.bits */
kusano fc6ab3
"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
kusano fc6ab3
"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
kusano fc6ab3
kusano fc6ab3
"        testb   %%al, %%al\n"
kusano fc6ab3
"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
kusano fc6ab3
kusano fc6ab3
"        shrl    $16, %%eax\n"            /* output this.val char */
kusano fc6ab3
"        stosb\n"
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_length_base:\n"
kusano fc6ab3
"        movl    %%eax, %%ecx\n"          /* len = this */
kusano fc6ab3
"        shrl    $16, %%ecx\n"            /* len = this.val */
kusano fc6ab3
"        movl    %%ecx, 64(%%esp)\n"      /* save len */
kusano fc6ab3
"        movb    %%al, %%cl\n"
kusano fc6ab3
kusano fc6ab3
"        testb   $16, %%al\n"
kusano fc6ab3
"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
kusano fc6ab3
"        andb    $15, %%cl\n"             /* op &= 15 */
kusano fc6ab3
"        jz      .L_decode_distance\n"    /* if (!op) */
kusano fc6ab3
"        cmpb    %%cl, %%bl\n"
kusano fc6ab3
"        jae     .L_add_bits_to_len\n"    /* if (op <= bits) */
kusano fc6ab3
kusano fc6ab3
"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        lodsw\n"                         /* al = *(ushort *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $16, %%bl\n"             /* bits += 16 */
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
"        movb    %%ch, %%cl\n"            /* move op back to ecx */
kusano fc6ab3
kusano fc6ab3
".L_add_bits_to_len:\n"
kusano fc6ab3
"        subb    %%cl, %%bl\n"
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        shrl    %%cl, %%edx\n"
kusano fc6ab3
"        addl    %%eax, 64(%%esp)\n"      /* len += hold & mask[op] */
kusano fc6ab3
kusano fc6ab3
".L_decode_distance:\n"
kusano fc6ab3
"        cmpb    $15, %%bl\n"
kusano fc6ab3
"        ja      .L_get_distance_code\n"  /* if (15 < bits) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        lodsw\n"                         /* al = *(ushort *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $16, %%bl\n"             /* bits += 16 */
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
".L_get_distance_code:\n"
kusano fc6ab3
"        movl    60(%%esp), %%eax\n"      /* eax = dmask */
kusano fc6ab3
"        movl    36(%%esp), %%ecx\n"      /* ecx = dcode */
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        movl    (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */
kusano fc6ab3
kusano fc6ab3
".L_dodist:\n"
kusano fc6ab3
"        movl    %%eax, %%ebp\n"          /* dist = this */
kusano fc6ab3
"        shrl    $16, %%ebp\n"            /* dist = this.val */
kusano fc6ab3
"        movb    %%ah, %%cl\n"
kusano fc6ab3
"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
kusano fc6ab3
"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
kusano fc6ab3
"        movb    %%al, %%cl\n"            /* cl = this.op */
kusano fc6ab3
kusano fc6ab3
"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
kusano fc6ab3
"        jz      .L_test_for_second_level_dist\n"
kusano fc6ab3
"        andb    $15, %%cl\n"             /* op &= 15 */
kusano fc6ab3
"        jz      .L_check_dist_one\n"
kusano fc6ab3
"        cmpb    %%cl, %%bl\n"
kusano fc6ab3
"        jae     .L_add_bits_to_dist\n"   /* if (op <= bits) 97.6% */
kusano fc6ab3
kusano fc6ab3
"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        lodsw\n"                         /* al = *(ushort *)in++ */
kusano fc6ab3
"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
kusano fc6ab3
"        addb    $16, %%bl\n"             /* bits += 16 */
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
"        movb    %%ch, %%cl\n"            /* move op back to ecx */
kusano fc6ab3
kusano fc6ab3
".L_add_bits_to_dist:\n"
kusano fc6ab3
"        subb    %%cl, %%bl\n"
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"                 /* (1 << op) - 1 */
kusano fc6ab3
"        andl    %%edx, %%eax\n"          /* eax &= hold */
kusano fc6ab3
"        shrl    %%cl, %%edx\n"
kusano fc6ab3
"        addl    %%eax, %%ebp\n"          /* dist += hold & ((1 << op) - 1) */
kusano fc6ab3
kusano fc6ab3
".L_check_window:\n"
kusano fc6ab3
"        movl    %%esi, 8(%%esp)\n"       /* save in so from can use it's reg */
kusano fc6ab3
"        movl    %%edi, %%eax\n"
kusano fc6ab3
"        subl    20(%%esp), %%eax\n"      /* nbytes = out - beg */
kusano fc6ab3
kusano fc6ab3
"        cmpl    %%ebp, %%eax\n"
kusano fc6ab3
"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
kusano fc6ab3
kusano fc6ab3
"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
kusano fc6ab3
"        movl    %%edi, %%esi\n"
kusano fc6ab3
"        subl    %%ebp, %%esi\n"          /* from = out - dist */
kusano fc6ab3
kusano fc6ab3
"        sarl    %%ecx\n"
kusano fc6ab3
"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
kusano fc6ab3
kusano fc6ab3
"        rep     movsw\n"
kusano fc6ab3
"        movb    (%%esi), %%al\n"
kusano fc6ab3
"        movb    %%al, (%%edi)\n"
kusano fc6ab3
"        incl    %%edi\n"
kusano fc6ab3
kusano fc6ab3
"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
kusano fc6ab3
"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".L_copy_two:\n"
kusano fc6ab3
"        rep     movsw\n"
kusano fc6ab3
"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
kusano fc6ab3
"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_check_dist_one:\n"
kusano fc6ab3
"        cmpl    $1, %%ebp\n"            /* if dist 1, is a memset */
kusano fc6ab3
"        jne     .L_check_window\n"
kusano fc6ab3
"        cmpl    %%edi, 20(%%esp)\n"
kusano fc6ab3
"        je      .L_check_window\n"      /* out == beg, if outside window */
kusano fc6ab3
kusano fc6ab3
"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
kusano fc6ab3
"        movb    -1(%%edi), %%al\n"
kusano fc6ab3
"        movb    %%al, %%ah\n"
kusano fc6ab3
kusano fc6ab3
"        sarl    %%ecx\n"
kusano fc6ab3
"        jnc     .L_set_two\n"
kusano fc6ab3
"        movb    %%al, (%%edi)\n"
kusano fc6ab3
"        incl    %%edi\n"
kusano fc6ab3
kusano fc6ab3
".L_set_two:\n"
kusano fc6ab3
"        rep     stosw\n"
kusano fc6ab3
"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_second_level_length:\n"
kusano fc6ab3
"        testb   $64, %%al\n"
kusano fc6ab3
"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"         /* eax &= hold */
kusano fc6ab3
"        addl    64(%%esp), %%eax\n"     /* eax += len */
kusano fc6ab3
"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
kusano fc6ab3
"        jmp     .L_dolen\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_test_for_second_level_dist:\n"
kusano fc6ab3
"        testb   $64, %%al\n"
kusano fc6ab3
"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
"        xorl    %%eax, %%eax\n"
kusano fc6ab3
"        incl    %%eax\n"
kusano fc6ab3
"        shll    %%cl, %%eax\n"
kusano fc6ab3
"        decl    %%eax\n"
kusano fc6ab3
"        andl    %%edx, %%eax\n"         /* eax &= hold */
kusano fc6ab3
"        addl    %%ebp, %%eax\n"         /* eax += dist */
kusano fc6ab3
"        movl    36(%%esp), %%ecx\n"     /* ecx = dcode */
kusano fc6ab3
"        movl    (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
kusano fc6ab3
"        jmp     .L_dodist\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_clip_window:\n"
kusano fc6ab3
"        movl    %%eax, %%ecx\n"
kusano fc6ab3
"        movl    48(%%esp), %%eax\n"     /* eax = wsize */
kusano fc6ab3
"        negl    %%ecx\n"                /* nbytes = -nbytes */
kusano fc6ab3
"        movl    28(%%esp), %%esi\n"     /* from = window */
kusano fc6ab3
kusano fc6ab3
"        cmpl    %%ebp, %%eax\n"
kusano fc6ab3
"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
kusano fc6ab3
kusano fc6ab3
"        addl    %%ebp, %%ecx\n"         /* nbytes = dist - nbytes */
kusano fc6ab3
"        cmpl    $0, 52(%%esp)\n"
kusano fc6ab3
"        jne     .L_wrap_around_window\n" /* if (write != 0) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"
kusano fc6ab3
"        addl    %%eax, %%esi\n"         /* from += wsize - nbytes */
kusano fc6ab3
kusano fc6ab3
"        movl    64(%%esp), %%eax\n"     /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movl    %%edi, %%esi\n"
kusano fc6ab3
"        subl    %%ebp, %%esi\n"         /* from = out - dist */
kusano fc6ab3
"        jmp     .L_do_copy\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_wrap_around_window:\n"
kusano fc6ab3
"        movl    52(%%esp), %%eax\n"     /* eax = write */
kusano fc6ab3
"        cmpl    %%eax, %%ecx\n"
kusano fc6ab3
"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
kusano fc6ab3
kusano fc6ab3
"        addl    48(%%esp), %%esi\n"     /* from += wsize */
kusano fc6ab3
"        addl    %%eax, %%esi\n"         /* from += write */
kusano fc6ab3
"        subl    %%ecx, %%esi\n"         /* from -= nbytes */
kusano fc6ab3
"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
kusano fc6ab3
kusano fc6ab3
"        movl    64(%%esp), %%eax\n"     /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movl    28(%%esp), %%esi\n"     /* from = window */
kusano fc6ab3
"        movl    52(%%esp), %%ecx\n"     /* nbytes = write */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movl    %%edi, %%esi\n"
kusano fc6ab3
"        subl    %%ebp, %%esi\n"         /* from = out - dist */
kusano fc6ab3
"        jmp     .L_do_copy\n"
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_contiguous_in_window:\n"
kusano fc6ab3
"        addl    %%eax, %%esi\n"
kusano fc6ab3
"        subl    %%ecx, %%esi\n"         /* from += write - nbytes */
kusano fc6ab3
kusano fc6ab3
"        movl    64(%%esp), %%eax\n"     /* eax = len */
kusano fc6ab3
"        cmpl    %%ecx, %%eax\n"
kusano fc6ab3
"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
"        movl    %%edi, %%esi\n"
kusano fc6ab3
"        subl    %%ebp, %%esi\n"         /* from = out - dist */
kusano fc6ab3
"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
".align 32,0x90\n"
kusano fc6ab3
".L_do_copy:\n"
kusano fc6ab3
"        movl    %%eax, %%ecx\n"
kusano fc6ab3
"        rep     movsb\n"
kusano fc6ab3
kusano fc6ab3
"        movl    8(%%esp), %%esi\n"      /* move in back to %esi, toss from */
kusano fc6ab3
"        movl    32(%%esp), %%ebp\n"     /* ebp = lcode */
kusano fc6ab3
"        jmp     .L_while_test\n"
kusano fc6ab3
kusano fc6ab3
".L_test_for_end_of_block:\n"
kusano fc6ab3
"        testb   $32, %%al\n"
kusano fc6ab3
"        jz      .L_invalid_literal_length_code\n"
kusano fc6ab3
"        movl    $1, 72(%%esp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_literal_length_code:\n"
kusano fc6ab3
"        movl    $2, 72(%%esp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_distance_code:\n"
kusano fc6ab3
"        movl    $3, 72(%%esp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_invalid_distance_too_far:\n"
kusano fc6ab3
"        movl    8(%%esp), %%esi\n"
kusano fc6ab3
"        movl    $4, 72(%%esp)\n"
kusano fc6ab3
"        jmp     .L_break_loop_with_status\n"
kusano fc6ab3
kusano fc6ab3
".L_break_loop:\n"
kusano fc6ab3
"        movl    $0, 72(%%esp)\n"
kusano fc6ab3
kusano fc6ab3
".L_break_loop_with_status:\n"
kusano fc6ab3
/* put in, out, bits, and hold back into ar and pop esp */
kusano fc6ab3
"        movl    %%esi, 8(%%esp)\n"      /* save in */
kusano fc6ab3
"        movl    %%edi, 16(%%esp)\n"     /* save out */
kusano fc6ab3
"        movl    %%ebx, 44(%%esp)\n"     /* save bits */
kusano fc6ab3
"        movl    %%edx, 40(%%esp)\n"     /* save hold */
kusano fc6ab3
"        movl    4(%%esp), %%ebp\n"      /* restore esp, ebp */
kusano fc6ab3
"        movl    (%%esp), %%esp\n"
kusano fc6ab3
          :
kusano fc6ab3
          : "m" (ar)
kusano fc6ab3
          : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
kusano fc6ab3
    );
kusano fc6ab3
#elif defined( _MSC_VER ) && ! defined( _M_AMD64 )
kusano fc6ab3
    __asm {
kusano fc6ab3
	lea	eax, ar
kusano fc6ab3
	mov	[eax], esp         /* save esp, ebp */
kusano fc6ab3
	mov	[eax+4], ebp
kusano fc6ab3
	mov	esp, eax
kusano fc6ab3
	mov	esi, [esp+8]       /* esi = in */
kusano fc6ab3
	mov	edi, [esp+16]      /* edi = out */
kusano fc6ab3
	mov	edx, [esp+40]      /* edx = hold */
kusano fc6ab3
	mov	ebx, [esp+44]      /* ebx = bits */
kusano fc6ab3
	mov	ebp, [esp+32]      /* ebp = lcode */
kusano fc6ab3
kusano fc6ab3
	cld
kusano fc6ab3
	jmp	L_do_loop
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_while_test:
kusano fc6ab3
	cmp	[esp+24], edi
kusano fc6ab3
	jbe	L_break_loop
kusano fc6ab3
	cmp	[esp+12], esi
kusano fc6ab3
	jbe	L_break_loop
kusano fc6ab3
kusano fc6ab3
L_do_loop:
kusano fc6ab3
	cmp	bl, 15
kusano fc6ab3
	ja	L_get_length_code    /* if (15 < bits) */
kusano fc6ab3
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	lodsw                         /* al = *(ushort *)in++ */
kusano fc6ab3
	mov	cl, bl            /* cl = bits, needs it for shifting */
kusano fc6ab3
	add	bl, 16             /* bits += 16 */
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
L_get_length_code:
kusano fc6ab3
	mov	eax, [esp+56]      /* eax = lmask */
kusano fc6ab3
	and	eax, edx          /* eax &= hold */
kusano fc6ab3
	mov	eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
kusano fc6ab3
kusano fc6ab3
L_dolen:
kusano fc6ab3
	mov	cl, ah            /* cl = this.bits */
kusano fc6ab3
	sub	bl, ah            /* bits -= this.bits */
kusano fc6ab3
	shr	edx, cl           /* hold >>= this.bits */
kusano fc6ab3
kusano fc6ab3
	test	al, al
kusano fc6ab3
	jnz	L_test_for_length_base /* if (op != 0) 45.7% */
kusano fc6ab3
kusano fc6ab3
	shr	eax, 16            /* output this.val char */
kusano fc6ab3
	stosb
kusano fc6ab3
	jmp	L_while_test
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_test_for_length_base:
kusano fc6ab3
	mov	ecx, eax          /* len = this */
kusano fc6ab3
	shr	ecx, 16            /* len = this.val */
kusano fc6ab3
	mov	[esp+64], ecx      /* save len */
kusano fc6ab3
	mov	cl, al
kusano fc6ab3
kusano fc6ab3
	test	al, 16
kusano fc6ab3
	jz	L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
kusano fc6ab3
	and	cl, 15             /* op &= 15 */
kusano fc6ab3
	jz	L_decode_distance    /* if (!op) */
kusano fc6ab3
	cmp	bl, cl
kusano fc6ab3
	jae	L_add_bits_to_len    /* if (op <= bits) */
kusano fc6ab3
kusano fc6ab3
	mov	ch, cl            /* stash op in ch, freeing cl */
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	lodsw                         /* al = *(ushort *)in++ */
kusano fc6ab3
	mov	cl, bl            /* cl = bits, needs it for shifting */
kusano fc6ab3
	add	bl, 16             /* bits += 16 */
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
	mov	cl, ch            /* move op back to ecx */
kusano fc6ab3
kusano fc6ab3
L_add_bits_to_len:
kusano fc6ab3
	sub	bl, cl
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	inc	eax
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	dec	eax
kusano fc6ab3
	and	eax, edx          /* eax &= hold */
kusano fc6ab3
	shr	edx, cl
kusano fc6ab3
	add	[esp+64], eax      /* len += hold & mask[op] */
kusano fc6ab3
kusano fc6ab3
L_decode_distance:
kusano fc6ab3
	cmp	bl, 15
kusano fc6ab3
	ja	L_get_distance_code  /* if (15 < bits) */
kusano fc6ab3
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	lodsw                         /* al = *(ushort *)in++ */
kusano fc6ab3
	mov	cl, bl            /* cl = bits, needs it for shifting */
kusano fc6ab3
	add	bl, 16             /* bits += 16 */
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
kusano fc6ab3
L_get_distance_code:
kusano fc6ab3
	mov	eax, [esp+60]      /* eax = dmask */
kusano fc6ab3
	mov	ecx, [esp+36]      /* ecx = dcode */
kusano fc6ab3
	and	eax, edx          /* eax &= hold */
kusano fc6ab3
	mov	eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
kusano fc6ab3
kusano fc6ab3
L_dodist:
kusano fc6ab3
	mov	ebp, eax          /* dist = this */
kusano fc6ab3
	shr	ebp, 16            /* dist = this.val */
kusano fc6ab3
	mov	cl, ah
kusano fc6ab3
	sub	bl, ah            /* bits -= this.bits */
kusano fc6ab3
	shr	edx, cl           /* hold >>= this.bits */
kusano fc6ab3
	mov	cl, al            /* cl = this.op */
kusano fc6ab3
kusano fc6ab3
	test	al, 16             /* if ((op & 16) == 0) */
kusano fc6ab3
	jz	L_test_for_second_level_dist
kusano fc6ab3
	and	cl, 15             /* op &= 15 */
kusano fc6ab3
	jz	L_check_dist_one
kusano fc6ab3
	cmp	bl, cl
kusano fc6ab3
	jae	L_add_bits_to_dist   /* if (op <= bits) 97.6% */
kusano fc6ab3
kusano fc6ab3
	mov	ch, cl            /* stash op in ch, freeing cl */
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	lodsw                         /* al = *(ushort *)in++ */
kusano fc6ab3
	mov	cl, bl            /* cl = bits, needs it for shifting */
kusano fc6ab3
	add	bl, 16             /* bits += 16 */
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
kusano fc6ab3
	mov	cl, ch            /* move op back to ecx */
kusano fc6ab3
kusano fc6ab3
L_add_bits_to_dist:
kusano fc6ab3
	sub	bl, cl
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	inc	eax
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	dec	eax                 /* (1 << op) - 1 */
kusano fc6ab3
	and	eax, edx          /* eax &= hold */
kusano fc6ab3
	shr	edx, cl
kusano fc6ab3
	add	ebp, eax          /* dist += hold & ((1 << op) - 1) */
kusano fc6ab3
kusano fc6ab3
L_check_window:
kusano fc6ab3
	mov	[esp+8], esi       /* save in so from can use it's reg */
kusano fc6ab3
	mov	eax, edi
kusano fc6ab3
	sub	eax, [esp+20]      /* nbytes = out - beg */
kusano fc6ab3
kusano fc6ab3
	cmp	eax, ebp
kusano fc6ab3
	jb	L_clip_window        /* if (dist > nbytes) 4.2% */
kusano fc6ab3
kusano fc6ab3
	mov	ecx, [esp+64]      /* ecx = len */
kusano fc6ab3
	mov	esi, edi
kusano fc6ab3
	sub	esi, ebp          /* from = out - dist */
kusano fc6ab3
kusano fc6ab3
	sar	ecx, 1
kusano fc6ab3
	jnc	L_copy_two
kusano fc6ab3
kusano fc6ab3
	rep     movsw
kusano fc6ab3
	mov	al, [esi]
kusano fc6ab3
	mov	[edi], al
kusano fc6ab3
	inc	edi
kusano fc6ab3
kusano fc6ab3
	mov	esi, [esp+8]      /* move in back to %esi, toss from */
kusano fc6ab3
	mov	ebp, [esp+32]     /* ebp = lcode */
kusano fc6ab3
	jmp	L_while_test
kusano fc6ab3
kusano fc6ab3
L_copy_two:
kusano fc6ab3
	rep     movsw
kusano fc6ab3
	mov	esi, [esp+8]      /* move in back to %esi, toss from */
kusano fc6ab3
	mov	ebp, [esp+32]     /* ebp = lcode */
kusano fc6ab3
	jmp	L_while_test
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_check_dist_one:
kusano fc6ab3
	cmp	ebp, 1            /* if dist 1, is a memset */
kusano fc6ab3
	jne	L_check_window
kusano fc6ab3
	cmp	[esp+20], edi
kusano fc6ab3
	je	L_check_window    /* out == beg, if outside window */
kusano fc6ab3
kusano fc6ab3
	mov	ecx, [esp+64]     /* ecx = len */
kusano fc6ab3
	mov	al, [edi-1]
kusano fc6ab3
	mov	ah, al
kusano fc6ab3
kusano fc6ab3
	sar	ecx, 1
kusano fc6ab3
	jnc	L_set_two
kusano fc6ab3
	mov	[edi], al         /* memset out with from[-1] */
kusano fc6ab3
	inc	edi
kusano fc6ab3
kusano fc6ab3
L_set_two:
kusano fc6ab3
	rep     stosw
kusano fc6ab3
	mov	ebp, [esp+32]     /* ebp = lcode */
kusano fc6ab3
	jmp	L_while_test
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_test_for_second_level_length:
kusano fc6ab3
	test	al, 64
kusano fc6ab3
	jnz	L_test_for_end_of_block /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	inc	eax
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	dec	eax
kusano fc6ab3
	and	eax, edx         /* eax &= hold */
kusano fc6ab3
	add	eax, [esp+64]     /* eax += len */
kusano fc6ab3
	mov	eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
kusano fc6ab3
	jmp	L_dolen
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_test_for_second_level_dist:
kusano fc6ab3
	test	al, 64
kusano fc6ab3
	jnz	L_invalid_distance_code /* if ((op & 64) != 0) */
kusano fc6ab3
kusano fc6ab3
	xor	eax, eax
kusano fc6ab3
	inc	eax
kusano fc6ab3
	shl	eax, cl
kusano fc6ab3
	dec	eax
kusano fc6ab3
	and	eax, edx         /* eax &= hold */
kusano fc6ab3
	add	eax, ebp         /* eax += dist */
kusano fc6ab3
	mov	ecx, [esp+36]     /* ecx = dcode */
kusano fc6ab3
	mov	eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
kusano fc6ab3
	jmp	L_dodist
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_clip_window:
kusano fc6ab3
	mov	ecx, eax
kusano fc6ab3
	mov	eax, [esp+48]     /* eax = wsize */
kusano fc6ab3
	neg	ecx                /* nbytes = -nbytes */
kusano fc6ab3
	mov	esi, [esp+28]     /* from = window */
kusano fc6ab3
kusano fc6ab3
	cmp	eax, ebp
kusano fc6ab3
	jb	L_invalid_distance_too_far /* if (dist > wsize) */
kusano fc6ab3
kusano fc6ab3
	add	ecx, ebp         /* nbytes = dist - nbytes */
kusano fc6ab3
	cmp	dword ptr [esp+52], 0
kusano fc6ab3
	jne	L_wrap_around_window /* if (write != 0) */
kusano fc6ab3
kusano fc6ab3
	sub	eax, ecx
kusano fc6ab3
	add	esi, eax         /* from += wsize - nbytes */
kusano fc6ab3
kusano fc6ab3
	mov	eax, [esp+64]    /* eax = len */
kusano fc6ab3
	cmp	eax, ecx
kusano fc6ab3
	jbe	L_do_copy          /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
	sub	eax, ecx         /* len -= nbytes */
kusano fc6ab3
	rep     movsb
kusano fc6ab3
	mov	esi, edi
kusano fc6ab3
	sub	esi, ebp         /* from = out - dist */
kusano fc6ab3
	jmp	L_do_copy
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_wrap_around_window:
kusano fc6ab3
	mov	eax, [esp+52]    /* eax = write */
kusano fc6ab3
	cmp	ecx, eax
kusano fc6ab3
	jbe	L_contiguous_in_window /* if (write >= nbytes) */
kusano fc6ab3
kusano fc6ab3
	add	esi, [esp+48]    /* from += wsize */
kusano fc6ab3
	add	esi, eax         /* from += write */
kusano fc6ab3
	sub	esi, ecx         /* from -= nbytes */
kusano fc6ab3
	sub	ecx, eax         /* nbytes -= write */
kusano fc6ab3
kusano fc6ab3
	mov	eax, [esp+64]    /* eax = len */
kusano fc6ab3
	cmp	eax, ecx
kusano fc6ab3
	jbe	L_do_copy          /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
	sub	eax, ecx         /* len -= nbytes */
kusano fc6ab3
	rep     movsb
kusano fc6ab3
	mov	esi, [esp+28]     /* from = window */
kusano fc6ab3
	mov	ecx, [esp+52]     /* nbytes = write */
kusano fc6ab3
	cmp	eax, ecx
kusano fc6ab3
	jbe	L_do_copy          /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
	sub	eax, ecx         /* len -= nbytes */
kusano fc6ab3
	rep     movsb
kusano fc6ab3
	mov	esi, edi
kusano fc6ab3
	sub	esi, ebp         /* from = out - dist */
kusano fc6ab3
	jmp	L_do_copy
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_contiguous_in_window:
kusano fc6ab3
	add	esi, eax
kusano fc6ab3
	sub	esi, ecx         /* from += write - nbytes */
kusano fc6ab3
kusano fc6ab3
	mov	eax, [esp+64]    /* eax = len */
kusano fc6ab3
	cmp	eax, ecx
kusano fc6ab3
	jbe	L_do_copy          /* if (nbytes >= len) */
kusano fc6ab3
kusano fc6ab3
	sub	eax, ecx         /* len -= nbytes */
kusano fc6ab3
	rep     movsb
kusano fc6ab3
	mov	esi, edi
kusano fc6ab3
	sub	esi, ebp         /* from = out - dist */
kusano fc6ab3
	jmp	L_do_copy
kusano fc6ab3
kusano fc6ab3
ALIGN 4
kusano fc6ab3
L_do_copy:
kusano fc6ab3
	mov	ecx, eax
kusano fc6ab3
	rep     movsb
kusano fc6ab3
kusano fc6ab3
	mov	esi, [esp+8]      /* move in back to %esi, toss from */
kusano fc6ab3
	mov	ebp, [esp+32]     /* ebp = lcode */
kusano fc6ab3
	jmp	L_while_test
kusano fc6ab3
kusano fc6ab3
L_test_for_end_of_block:
kusano fc6ab3
	test	al, 32
kusano fc6ab3
	jz	L_invalid_literal_length_code
kusano fc6ab3
	mov	dword ptr [esp+72], 1
kusano fc6ab3
	jmp	L_break_loop_with_status
kusano fc6ab3
kusano fc6ab3
L_invalid_literal_length_code:
kusano fc6ab3
	mov	dword ptr [esp+72], 2
kusano fc6ab3
	jmp	L_break_loop_with_status
kusano fc6ab3
kusano fc6ab3
L_invalid_distance_code:
kusano fc6ab3
	mov	dword ptr [esp+72], 3
kusano fc6ab3
	jmp	L_break_loop_with_status
kusano fc6ab3
kusano fc6ab3
L_invalid_distance_too_far:
kusano fc6ab3
	mov	esi, [esp+4]
kusano fc6ab3
	mov	dword ptr [esp+72], 4
kusano fc6ab3
	jmp	L_break_loop_with_status
kusano fc6ab3
kusano fc6ab3
L_break_loop:
kusano fc6ab3
	mov	dword ptr [esp+72], 0
kusano fc6ab3
kusano fc6ab3
L_break_loop_with_status:
kusano fc6ab3
/* put in, out, bits, and hold back into ar and pop esp */
kusano fc6ab3
	mov	[esp+8], esi     /* save in */
kusano fc6ab3
	mov	[esp+16], edi    /* save out */
kusano fc6ab3
	mov	[esp+44], ebx    /* save bits */
kusano fc6ab3
	mov	[esp+40], edx    /* save hold */
kusano fc6ab3
	mov	ebp, [esp+4]     /* restore esp, ebp */
kusano fc6ab3
	mov	esp, [esp]
kusano fc6ab3
    }
kusano fc6ab3
#else
kusano fc6ab3
#error "x86 architecture not defined"
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
    if (ar.status > 1) {
kusano fc6ab3
        if (ar.status == 2)
kusano fc6ab3
            strm->msg = "invalid literal/length code";
kusano fc6ab3
        else if (ar.status == 3)
kusano fc6ab3
            strm->msg = "invalid distance code";
kusano fc6ab3
        else
kusano fc6ab3
            strm->msg = "invalid distance too far back";
kusano fc6ab3
        state->mode = BAD;
kusano fc6ab3
    }
kusano fc6ab3
    else if ( ar.status == 1 ) {
kusano fc6ab3
        state->mode = TYPE;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
kusano fc6ab3
    ar.len = ar.bits >> 3;
kusano fc6ab3
    ar.in -= ar.len;
kusano fc6ab3
    ar.bits -= ar.len << 3;
kusano fc6ab3
    ar.hold &= (1U << ar.bits) - 1;
kusano fc6ab3
kusano fc6ab3
    /* update state and return */
kusano fc6ab3
    strm->next_in = ar.in;
kusano fc6ab3
    strm->next_out = ar.out;
kusano fc6ab3
    strm->avail_in = (unsigned)(ar.in < ar.last ?
kusano fc6ab3
                                PAD_AVAIL_IN + (ar.last - ar.in) :
kusano fc6ab3
                                PAD_AVAIL_IN - (ar.in - ar.last));
kusano fc6ab3
    strm->avail_out = (unsigned)(ar.out < ar.end ?
kusano fc6ab3
                                 PAD_AVAIL_OUT + (ar.end - ar.out) :
kusano fc6ab3
                                 PAD_AVAIL_OUT - (ar.out - ar.end));
kusano fc6ab3
    state->hold = ar.hold;
kusano fc6ab3
    state->bits = ar.bits;
kusano fc6ab3
    return;
kusano fc6ab3
}
kusano fc6ab3