source: rtems/cpukit/zlib/contrib/inflate86/inffas86.c @ 416fb2ba

4.115
Last change on this file since 416fb2ba was 416fb2ba, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/18/11 at 10:11:34

Import from zlib-1.2.4

  • Property mode set to 100644
File size: 39.7 KB
Line 
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@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 */
71void inflate_fast(strm, start)
72z_streamp strm;
73unsigned 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
812ALIGN 4
813L_while_test:
814        cmp     [esp+24], edi
815        jbe     L_break_loop
816        cmp     [esp+12], esi
817        jbe     L_break_loop
818
819L_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
830L_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
835L_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
847ALIGN 4
848L_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
870L_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
880L_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
891L_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
897L_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
921L_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
931L_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
955L_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
961ALIGN 4
962L_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
977L_set_two:
978        rep     stosw
979        mov     ebp, [esp+32]     /* ebp = lcode */
980        jmp     L_while_test
981
982ALIGN 4
983L_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
996ALIGN 4
997L_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
1011ALIGN 4
1012L_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
1038ALIGN 4
1039L_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
1066ALIGN 4
1067L_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
1081ALIGN 4
1082L_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
1090L_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
1096L_invalid_literal_length_code:
1097        mov     dword ptr [esp+72], 2
1098        jmp     L_break_loop_with_status
1099
1100L_invalid_distance_code:
1101        mov     dword ptr [esp+72], 3
1102        jmp     L_break_loop_with_status
1103
1104L_invalid_distance_too_far:
1105        mov     esi, [esp+4]
1106        mov     dword ptr [esp+72], 4
1107        jmp     L_break_loop_with_status
1108
1109L_break_loop:
1110        mov     dword ptr [esp+72], 0
1111
1112L_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
Note: See TracBrowser for help on using the repository browser.