inffas86.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:40k
源码类别:

通讯编程

开发平台:

Visual C++

  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. #include "zutil.h"
  29. #include "inftrees.h"
  30. #include "inflate.h"
  31. #include "inffast.h"
  32. /* Mark Adler's comments from inffast.c: */
  33. /*
  34.    Decode literal, length, and distance codes and write out the resulting
  35.    literal and match bytes until either not enough input or output is
  36.    available, an end-of-block is encountered, or a data error is encountered.
  37.    When large enough input and output buffers are supplied to inflate(), for
  38.    example, a 16K input buffer and a 64K output buffer, more than 95% of the
  39.    inflate execution time is spent in this routine.
  40.    Entry assumptions:
  41.         state->mode == LEN
  42.         strm->avail_in >= 6
  43.         strm->avail_out >= 258
  44.         start >= strm->avail_out
  45.         state->bits < 8
  46.    On return, state->mode is one of:
  47.         LEN -- ran out of enough output space or enough available input
  48.         TYPE -- reached end of block code, inflate() to interpret next block
  49.         BAD -- error in block data
  50.    Notes:
  51.     - The maximum input bits used by a length/distance pair is 15 bits for the
  52.       length code, 5 bits for the length extra, 15 bits for the distance code,
  53.       and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
  54.       Therefore if strm->avail_in >= 6, then there is enough input to avoid
  55.       checking for available input while decoding.
  56.     - The maximum bytes that a single length/distance pair can output is 258
  57.       bytes, which is the maximum length that can be coded.  inflate_fast()
  58.       requires strm->avail_out >= 258 for each loop to avoid checking for
  59.       output space.
  60.  */
  61. void inflate_fast(strm, start)
  62. z_streamp strm;
  63. unsigned start;         /* inflate()'s starting value for strm->avail_out */
  64. {
  65.     struct inflate_state FAR *state;
  66.     struct inffast_ar {
  67. /* 64   32                               x86  x86_64 */
  68. /* ar offset                              register */
  69. /*  0    0 */ void *esp;                /* esp save */
  70. /*  8    4 */ void *ebp;                /* ebp save */
  71. /* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
  72. /* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
  73. /* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
  74. /* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
  75. /* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
  76. /* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
  77. /* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
  78. /* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
  79. /* 80   40 */ unsigned long hold;       /* edx rdx  local strm->hold */
  80. /* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
  81. /* 92   48 */ unsigned wsize;           /*          window size */
  82. /* 96   52 */ unsigned write;           /*          window write index */
  83. /*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
  84. /*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
  85. /*108   64 */ unsigned len;             /*     r14  match length */
  86. /*112   68 */ unsigned dist;            /*     r15  match distance */
  87. /*116   72 */ unsigned status;          /*          set when state chng*/
  88.     } ar;
  89. #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
  90. #define PAD_AVAIL_IN 6
  91. #define PAD_AVAIL_OUT 258
  92. #else
  93. #define PAD_AVAIL_IN 5
  94. #define PAD_AVAIL_OUT 257
  95. #endif
  96.     /* copy state to local variables */
  97.     state = (struct inflate_state FAR *)strm->state;
  98.     ar.in = strm->next_in;
  99.     ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
  100.     ar.out = strm->next_out;
  101.     ar.beg = ar.out - (start - strm->avail_out);
  102.     ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
  103.     ar.wsize = state->wsize;
  104.     ar.write = state->write;
  105.     ar.window = state->window;
  106.     ar.hold = state->hold;
  107.     ar.bits = state->bits;
  108.     ar.lcode = state->lencode;
  109.     ar.dcode = state->distcode;
  110.     ar.lmask = (1U << state->lenbits) - 1;
  111.     ar.dmask = (1U << state->distbits) - 1;
  112.     /* decode literals and length/distances until end-of-block or not enough
  113.        input data or output space */
  114.     /* align in on 1/2 hold size boundary */
  115.     while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
  116.         ar.hold += (unsigned long)*ar.in++ << ar.bits;
  117.         ar.bits += 8;
  118.     }
  119. #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
  120.     __asm__ __volatile__ (
  121. "        leaq    %0, %%raxn"
  122. "        movq    %%rbp, 8(%%rax)n"       /* save regs rbp and rsp */
  123. "        movq    %%rsp, (%%rax)n"
  124. "        movq    %%rax, %%rspn"          /* make rsp point to &ar */
  125. "        movq    16(%%rsp), %%rsin"      /* rsi  = in */
  126. "        movq    32(%%rsp), %%rdin"      /* rdi  = out */
  127. "        movq    24(%%rsp), %%r9n"       /* r9   = last */
  128. "        movq    48(%%rsp), %%r10n"      /* r10  = end */
  129. "        movq    64(%%rsp), %%rbpn"      /* rbp  = lcode */
  130. "        movq    72(%%rsp), %%r11n"      /* r11  = dcode */
  131. "        movq    80(%%rsp), %%rdxn"      /* rdx  = hold */
  132. "        movl    88(%%rsp), %%ebxn"      /* ebx  = bits */
  133. "        movl    100(%%rsp), %%r12dn"    /* r12d = lmask */
  134. "        movl    104(%%rsp), %%r13dn"    /* r13d = dmask */
  135.                                           /* r14d = len */
  136.                                           /* r15d = dist */
  137. "        cldn"
  138. "        cmpq    %%rdi, %%r10n"
  139. "        je      .L_one_timen"           /* if only one decode left */
  140. "        cmpq    %%rsi, %%r9n"
  141. "        je      .L_one_timen"
  142. "        jmp     .L_do_loopn"
  143. ".L_one_time:n"
  144. "        movq    %%r12, %%r8n"           /* r8 = lmask */
  145. "        cmpb    $32, %%bln"
  146. "        ja      .L_get_length_code_one_timen"
  147. "        lodsln"                         /* eax = *(uint *)in++ */
  148. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  149. "        addb    $32, %%bln"             /* bits += 32 */
  150. "        shlq    %%cl, %%raxn"
  151. "        orq     %%rax, %%rdxn"          /* hold |= *((uint *)in)++ << bits */
  152. "        jmp     .L_get_length_code_one_timen"
  153. ".align 32,0x90n"
  154. ".L_while_test:n"
  155. "        cmpq    %%rdi, %%r10n"
  156. "        jbe     .L_break_loopn"
  157. "        cmpq    %%rsi, %%r9n"
  158. "        jbe     .L_break_loopn"
  159. ".L_do_loop:n"
  160. "        movq    %%r12, %%r8n"           /* r8 = lmask */
  161. "        cmpb    $32, %%bln"
  162. "        ja      .L_get_length_coden"    /* if (32 < bits) */
  163. "        lodsln"                         /* eax = *(uint *)in++ */
  164. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  165. "        addb    $32, %%bln"             /* bits += 32 */
  166. "        shlq    %%cl, %%raxn"
  167. "        orq     %%rax, %%rdxn"          /* hold |= *((uint *)in)++ << bits */
  168. ".L_get_length_code:n"
  169. "        andq    %%rdx, %%r8n"            /* r8 &= hold */
  170. "        movl    (%%rbp,%%r8,4), %%eaxn"  /* eax = lcode[hold & lmask] */
  171. "        movb    %%ah, %%cln"            /* cl = this.bits */
  172. "        subb    %%ah, %%bln"            /* bits -= this.bits */
  173. "        shrq    %%cl, %%rdxn"           /* hold >>= this.bits */
  174. "        testb   %%al, %%aln"
  175. "        jnz     .L_test_for_length_basen" /* if (op != 0) 45.7% */
  176. "        movq    %%r12, %%r8n"            /* r8 = lmask */
  177. "        shrl    $16, %%eaxn"            /* output this.val char */
  178. "        stosbn"
  179. ".L_get_length_code_one_time:n"
  180. "        andq    %%rdx, %%r8n"            /* r8 &= hold */
  181. "        movl    (%%rbp,%%r8,4), %%eaxn" /* eax = lcode[hold & lmask] */
  182. ".L_dolen:n"
  183. "        movb    %%ah, %%cln"            /* cl = this.bits */
  184. "        subb    %%ah, %%bln"            /* bits -= this.bits */
  185. "        shrq    %%cl, %%rdxn"           /* hold >>= this.bits */
  186. "        testb   %%al, %%aln"
  187. "        jnz     .L_test_for_length_basen" /* if (op != 0) 45.7% */
  188. "        shrl    $16, %%eaxn"            /* output this.val char */
  189. "        stosbn"
  190. "        jmp     .L_while_testn"
  191. ".align 32,0x90n"
  192. ".L_test_for_length_base:n"
  193. "        movl    %%eax, %%r14dn"         /* len = this */
  194. "        shrl    $16, %%r14dn"           /* len = this.val */
  195. "        movb    %%al, %%cln"
  196. "        testb   $16, %%aln"
  197. "        jz      .L_test_for_second_level_lengthn" /* if ((op & 16) == 0) 8% */
  198. "        andb    $15, %%cln"             /* op &= 15 */
  199. "        jz      .L_decode_distancen"    /* if (!op) */
  200. ".L_add_bits_to_len:n"
  201. "        subb    %%cl, %%bln"
  202. "        xorl    %%eax, %%eaxn"
  203. "        incl    %%eaxn"
  204. "        shll    %%cl, %%eaxn"
  205. "        decl    %%eaxn"
  206. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  207. "        shrq    %%cl, %%rdxn"
  208. "        addl    %%eax, %%r14dn"         /* len += hold & mask[op] */
  209. ".L_decode_distance:n"
  210. "        movq    %%r13, %%r8n"           /* r8 = dmask */
  211. "        cmpb    $32, %%bln"
  212. "        ja      .L_get_distance_coden"  /* if (32 < bits) */
  213. "        lodsln"                         /* eax = *(uint *)in++ */
  214. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  215. "        addb    $32, %%bln"             /* bits += 32 */
  216. "        shlq    %%cl, %%raxn"
  217. "        orq     %%rax, %%rdxn"          /* hold |= *((uint *)in)++ << bits */
  218. ".L_get_distance_code:n"
  219. "        andq    %%rdx, %%r8n"           /* r8 &= hold */
  220. "        movl    (%%r11,%%r8,4), %%eaxn" /* eax = dcode[hold & dmask] */
  221. ".L_dodist:n"
  222. "        movl    %%eax, %%r15dn"         /* dist = this */
  223. "        shrl    $16, %%r15dn"           /* dist = this.val */
  224. "        movb    %%ah, %%cln"
  225. "        subb    %%ah, %%bln"            /* bits -= this.bits */
  226. "        shrq    %%cl, %%rdxn"           /* hold >>= this.bits */
  227. "        movb    %%al, %%cln"            /* cl = this.op */
  228. "        testb   $16, %%aln"             /* if ((op & 16) == 0) */
  229. "        jz      .L_test_for_second_level_distn"
  230. "        andb    $15, %%cln"             /* op &= 15 */
  231. "        jz      .L_check_dist_onen"
  232. ".L_add_bits_to_dist:n"
  233. "        subb    %%cl, %%bln"
  234. "        xorl    %%eax, %%eaxn"
  235. "        incl    %%eaxn"
  236. "        shll    %%cl, %%eaxn"
  237. "        decl    %%eaxn"                 /* (1 << op) - 1 */
  238. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  239. "        shrq    %%cl, %%rdxn"
  240. "        addl    %%eax, %%r15dn"         /* dist += hold & ((1 << op) - 1) */
  241. ".L_check_window:n"
  242. "        movq    %%rsi, %%r8n"           /* save in so from can use it's reg */
  243. "        movq    %%rdi, %%raxn"
  244. "        subq    40(%%rsp), %%raxn"      /* nbytes = out - beg */
  245. "        cmpl    %%r15d, %%eaxn"
  246. "        jb      .L_clip_windown"        /* if (dist > nbytes) 4.2% */
  247. "        movl    %%r14d, %%ecxn"         /* ecx = len */
  248. "        movq    %%rdi, %%rsin"
  249. "        subq    %%r15, %%rsin"          /* from = out - dist */
  250. "        sarl    %%ecxn"
  251. "        jnc     .L_copy_twon"           /* if len % 2 == 0 */
  252. "        rep     movswn"
  253. "        movb    (%%rsi), %%aln"
  254. "        movb    %%al, (%%rdi)n"
  255. "        incq    %%rdin"
  256. "        movq    %%r8, %%rsin"           /* move in back to %rsi, toss from */
  257. "        jmp     .L_while_testn"
  258. ".L_copy_two:n"
  259. "        rep     movswn"
  260. "        movq    %%r8, %%rsin"           /* move in back to %rsi, toss from */
  261. "        jmp     .L_while_testn"
  262. ".align 32,0x90n"
  263. ".L_check_dist_one:n"
  264. "        cmpl    $1, %%r15dn"            /* if dist 1, is a memset */
  265. "        jne     .L_check_windown"
  266. "        cmpq    %%rdi, 40(%%rsp)n"      /* if out == beg, outside window */
  267. "        je      .L_check_windown"
  268. "        movl    %%r14d, %%ecxn"         /* ecx = len */
  269. "        movb    -1(%%rdi), %%aln"
  270. "        movb    %%al, %%ahn"
  271. "        sarl    %%ecxn"
  272. "        jnc     .L_set_twon"
  273. "        movb    %%al, (%%rdi)n"
  274. "        incq    %%rdin"
  275. ".L_set_two:n"
  276. "        rep     stoswn"
  277. "        jmp     .L_while_testn"
  278. ".align 32,0x90n"
  279. ".L_test_for_second_level_length:n"
  280. "        testb   $64, %%aln"
  281. "        jnz     .L_test_for_end_of_blockn" /* if ((op & 64) != 0) */
  282. "        xorl    %%eax, %%eaxn"
  283. "        incl    %%eaxn"
  284. "        shll    %%cl, %%eaxn"
  285. "        decl    %%eaxn"
  286. "        andl    %%edx, %%eaxn"         /* eax &= hold */
  287. "        addl    %%r14d, %%eaxn"        /* eax += len */
  288. "        movl    (%%rbp,%%rax,4), %%eaxn" /* eax = lcode[val+(hold&mask[op])]*/
  289. "        jmp     .L_dolenn"
  290. ".align 32,0x90n"
  291. ".L_test_for_second_level_dist:n"
  292. "        testb   $64, %%aln"
  293. "        jnz     .L_invalid_distance_coden" /* if ((op & 64) != 0) */
  294. "        xorl    %%eax, %%eaxn"
  295. "        incl    %%eaxn"
  296. "        shll    %%cl, %%eaxn"
  297. "        decl    %%eaxn"
  298. "        andl    %%edx, %%eaxn"         /* eax &= hold */
  299. "        addl    %%r15d, %%eaxn"        /* eax += dist */
  300. "        movl    (%%r11,%%rax,4), %%eaxn" /* eax = dcode[val+(hold&mask[op])]*/
  301. "        jmp     .L_dodistn"
  302. ".align 32,0x90n"
  303. ".L_clip_window:n"
  304. "        movl    %%eax, %%ecxn"         /* ecx = nbytes */
  305. "        movl    92(%%rsp), %%eaxn"     /* eax = wsize, prepare for dist cmp */
  306. "        negl    %%ecxn"                /* nbytes = -nbytes */
  307. "        cmpl    %%r15d, %%eaxn"
  308. "        jb      .L_invalid_distance_too_farn" /* if (dist > wsize) */
  309. "        addl    %%r15d, %%ecxn"         /* nbytes = dist - nbytes */
  310. "        cmpl    $0, 96(%%rsp)n"
  311. "        jne     .L_wrap_around_windown" /* if (write != 0) */
  312. "        movq    56(%%rsp), %%rsin"     /* from  = window */
  313. "        subl    %%ecx, %%eaxn"         /* eax  -= nbytes */
  314. "        addq    %%rax, %%rsin"         /* from += wsize - nbytes */
  315. "        movl    %%r14d, %%eaxn"        /* eax = len */
  316. "        cmpl    %%ecx, %%r14dn"
  317. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  318. "        subl    %%ecx, %%eaxn"         /* eax -= nbytes */
  319. "        rep     movsbn"
  320. "        movq    %%rdi, %%rsin"
  321. "        subq    %%r15, %%rsin"         /* from = &out[ -dist ] */
  322. "        jmp     .L_do_copyn"
  323. ".align 32,0x90n"
  324. ".L_wrap_around_window:n"
  325. "        movl    96(%%rsp), %%eaxn"     /* eax = write */
  326. "        cmpl    %%eax, %%ecxn"
  327. "        jbe     .L_contiguous_in_windown" /* if (write >= nbytes) */
  328. "        movl    92(%%rsp), %%esin"     /* from  = wsize */
  329. "        addq    56(%%rsp), %%rsin"     /* from += window */
  330. "        addq    %%rax, %%rsin"         /* from += write */
  331. "        subq    %%rcx, %%rsin"         /* from -= nbytes */
  332. "        subl    %%eax, %%ecxn"         /* nbytes -= write */
  333. "        movl    %%r14d, %%eaxn"        /* eax = len */
  334. "        cmpl    %%ecx, %%eaxn"
  335. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  336. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  337. "        rep     movsbn"
  338. "        movq    56(%%rsp), %%rsin"     /* from = window */
  339. "        movl    96(%%rsp), %%ecxn"     /* nbytes = write */
  340. "        cmpl    %%ecx, %%eaxn"
  341. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  342. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  343. "        rep     movsbn"
  344. "        movq    %%rdi, %%rsin"
  345. "        subq    %%r15, %%rsin"         /* from = out - dist */
  346. "        jmp     .L_do_copyn"
  347. ".align 32,0x90n"
  348. ".L_contiguous_in_window:n"
  349. "        movq    56(%%rsp), %%rsin"     /* rsi = window */
  350. "        addq    %%rax, %%rsin"
  351. "        subq    %%rcx, %%rsin"         /* from += write - nbytes */
  352. "        movl    %%r14d, %%eaxn"        /* eax = len */
  353. "        cmpl    %%ecx, %%eaxn"
  354. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  355. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  356. "        rep     movsbn"
  357. "        movq    %%rdi, %%rsin"
  358. "        subq    %%r15, %%rsin"         /* from = out - dist */
  359. "        jmp     .L_do_copyn"           /* if (nbytes >= len) */
  360. ".align 32,0x90n"
  361. ".L_do_copy:n"
  362. "        movl    %%eax, %%ecxn"         /* ecx = len */
  363. "        rep     movsbn"
  364. "        movq    %%r8, %%rsin"          /* move in back to %esi, toss from */
  365. "        jmp     .L_while_testn"
  366. ".L_test_for_end_of_block:n"
  367. "        testb   $32, %%aln"
  368. "        jz      .L_invalid_literal_length_coden"
  369. "        movl    $1, 116(%%rsp)n"
  370. "        jmp     .L_break_loop_with_statusn"
  371. ".L_invalid_literal_length_code:n"
  372. "        movl    $2, 116(%%rsp)n"
  373. "        jmp     .L_break_loop_with_statusn"
  374. ".L_invalid_distance_code:n"
  375. "        movl    $3, 116(%%rsp)n"
  376. "        jmp     .L_break_loop_with_statusn"
  377. ".L_invalid_distance_too_far:n"
  378. "        movl    $4, 116(%%rsp)n"
  379. "        jmp     .L_break_loop_with_statusn"
  380. ".L_break_loop:n"
  381. "        movl    $0, 116(%%rsp)n"
  382. ".L_break_loop_with_status:n"
  383. /* put in, out, bits, and hold back into ar and pop esp */
  384. "        movq    %%rsi, 16(%%rsp)n"     /* in */
  385. "        movq    %%rdi, 32(%%rsp)n"     /* out */
  386. "        movl    %%ebx, 88(%%rsp)n"     /* bits */
  387. "        movq    %%rdx, 80(%%rsp)n"     /* hold */
  388. "        movq    (%%rsp), %%raxn"       /* restore rbp and rsp */
  389. "        movq    8(%%rsp), %%rbpn"
  390. "        movq    %%rax, %%rspn"
  391.           :
  392.           : "m" (ar)
  393.           : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
  394.             "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
  395.     );
  396. #elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 )
  397.     __asm__ __volatile__ (
  398. "        leal    %0, %%eaxn"
  399. "        movl    %%esp, (%%eax)n"        /* save esp, ebp */
  400. "        movl    %%ebp, 4(%%eax)n"
  401. "        movl    %%eax, %%espn"
  402. "        movl    8(%%esp), %%esin"       /* esi = in */
  403. "        movl    16(%%esp), %%edin"      /* edi = out */
  404. "        movl    40(%%esp), %%edxn"      /* edx = hold */
  405. "        movl    44(%%esp), %%ebxn"      /* ebx = bits */
  406. "        movl    32(%%esp), %%ebpn"      /* ebp = lcode */
  407. "        cldn"
  408. "        jmp     .L_do_loopn"
  409. ".align 32,0x90n"
  410. ".L_while_test:n"
  411. "        cmpl    %%edi, 24(%%esp)n"      /* out < end */
  412. "        jbe     .L_break_loopn"
  413. "        cmpl    %%esi, 12(%%esp)n"      /* in < last */
  414. "        jbe     .L_break_loopn"
  415. ".L_do_loop:n"
  416. "        cmpb    $15, %%bln"
  417. "        ja      .L_get_length_coden"    /* if (15 < bits) */
  418. "        xorl    %%eax, %%eaxn"
  419. "        lodswn"                         /* al = *(ushort *)in++ */
  420. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  421. "        addb    $16, %%bln"             /* bits += 16 */
  422. "        shll    %%cl, %%eaxn"
  423. "        orl     %%eax, %%edxn"        /* hold |= *((ushort *)in)++ << bits */
  424. ".L_get_length_code:n"
  425. "        movl    56(%%esp), %%eaxn"      /* eax = lmask */
  426. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  427. "        movl    (%%ebp,%%eax,4), %%eaxn" /* eax = lcode[hold & lmask] */
  428. ".L_dolen:n"
  429. "        movb    %%ah, %%cln"            /* cl = this.bits */
  430. "        subb    %%ah, %%bln"            /* bits -= this.bits */
  431. "        shrl    %%cl, %%edxn"           /* hold >>= this.bits */
  432. "        testb   %%al, %%aln"
  433. "        jnz     .L_test_for_length_basen" /* if (op != 0) 45.7% */
  434. "        shrl    $16, %%eaxn"            /* output this.val char */
  435. "        stosbn"
  436. "        jmp     .L_while_testn"
  437. ".align 32,0x90n"
  438. ".L_test_for_length_base:n"
  439. "        movl    %%eax, %%ecxn"          /* len = this */
  440. "        shrl    $16, %%ecxn"            /* len = this.val */
  441. "        movl    %%ecx, 64(%%esp)n"      /* save len */
  442. "        movb    %%al, %%cln"
  443. "        testb   $16, %%aln"
  444. "        jz      .L_test_for_second_level_lengthn" /* if ((op & 16) == 0) 8% */
  445. "        andb    $15, %%cln"             /* op &= 15 */
  446. "        jz      .L_decode_distancen"    /* if (!op) */
  447. "        cmpb    %%cl, %%bln"
  448. "        jae     .L_add_bits_to_lenn"    /* if (op <= bits) */
  449. "        movb    %%cl, %%chn"            /* stash op in ch, freeing cl */
  450. "        xorl    %%eax, %%eaxn"
  451. "        lodswn"                         /* al = *(ushort *)in++ */
  452. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  453. "        addb    $16, %%bln"             /* bits += 16 */
  454. "        shll    %%cl, %%eaxn"
  455. "        orl     %%eax, %%edxn"         /* hold |= *((ushort *)in)++ << bits */
  456. "        movb    %%ch, %%cln"            /* move op back to ecx */
  457. ".L_add_bits_to_len:n"
  458. "        subb    %%cl, %%bln"
  459. "        xorl    %%eax, %%eaxn"
  460. "        incl    %%eaxn"
  461. "        shll    %%cl, %%eaxn"
  462. "        decl    %%eaxn"
  463. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  464. "        shrl    %%cl, %%edxn"
  465. "        addl    %%eax, 64(%%esp)n"      /* len += hold & mask[op] */
  466. ".L_decode_distance:n"
  467. "        cmpb    $15, %%bln"
  468. "        ja      .L_get_distance_coden"  /* if (15 < bits) */
  469. "        xorl    %%eax, %%eaxn"
  470. "        lodswn"                         /* al = *(ushort *)in++ */
  471. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  472. "        addb    $16, %%bln"             /* bits += 16 */
  473. "        shll    %%cl, %%eaxn"
  474. "        orl     %%eax, %%edxn"         /* hold |= *((ushort *)in)++ << bits */
  475. ".L_get_distance_code:n"
  476. "        movl    60(%%esp), %%eaxn"      /* eax = dmask */
  477. "        movl    36(%%esp), %%ecxn"      /* ecx = dcode */
  478. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  479. "        movl    (%%ecx,%%eax,4), %%eaxn"/* eax = dcode[hold & dmask] */
  480. ".L_dodist:n"
  481. "        movl    %%eax, %%ebpn"          /* dist = this */
  482. "        shrl    $16, %%ebpn"            /* dist = this.val */
  483. "        movb    %%ah, %%cln"
  484. "        subb    %%ah, %%bln"            /* bits -= this.bits */
  485. "        shrl    %%cl, %%edxn"           /* hold >>= this.bits */
  486. "        movb    %%al, %%cln"            /* cl = this.op */
  487. "        testb   $16, %%aln"             /* if ((op & 16) == 0) */
  488. "        jz      .L_test_for_second_level_distn"
  489. "        andb    $15, %%cln"             /* op &= 15 */
  490. "        jz      .L_check_dist_onen"
  491. "        cmpb    %%cl, %%bln"
  492. "        jae     .L_add_bits_to_distn"   /* if (op <= bits) 97.6% */
  493. "        movb    %%cl, %%chn"            /* stash op in ch, freeing cl */
  494. "        xorl    %%eax, %%eaxn"
  495. "        lodswn"                         /* al = *(ushort *)in++ */
  496. "        movb    %%bl, %%cln"            /* cl = bits, needs it for shifting */
  497. "        addb    $16, %%bln"             /* bits += 16 */
  498. "        shll    %%cl, %%eaxn"
  499. "        orl     %%eax, %%edxn"        /* hold |= *((ushort *)in)++ << bits */
  500. "        movb    %%ch, %%cln"            /* move op back to ecx */
  501. ".L_add_bits_to_dist:n"
  502. "        subb    %%cl, %%bln"
  503. "        xorl    %%eax, %%eaxn"
  504. "        incl    %%eaxn"
  505. "        shll    %%cl, %%eaxn"
  506. "        decl    %%eaxn"                 /* (1 << op) - 1 */
  507. "        andl    %%edx, %%eaxn"          /* eax &= hold */
  508. "        shrl    %%cl, %%edxn"
  509. "        addl    %%eax, %%ebpn"          /* dist += hold & ((1 << op) - 1) */
  510. ".L_check_window:n"
  511. "        movl    %%esi, 8(%%esp)n"       /* save in so from can use it's reg */
  512. "        movl    %%edi, %%eaxn"
  513. "        subl    20(%%esp), %%eaxn"      /* nbytes = out - beg */
  514. "        cmpl    %%ebp, %%eaxn"
  515. "        jb      .L_clip_windown"        /* if (dist > nbytes) 4.2% */
  516. "        movl    64(%%esp), %%ecxn"      /* ecx = len */
  517. "        movl    %%edi, %%esin"
  518. "        subl    %%ebp, %%esin"          /* from = out - dist */
  519. "        sarl    %%ecxn"
  520. "        jnc     .L_copy_twon"           /* if len % 2 == 0 */
  521. "        rep     movswn"
  522. "        movb    (%%esi), %%aln"
  523. "        movb    %%al, (%%edi)n"
  524. "        incl    %%edin"
  525. "        movl    8(%%esp), %%esin"       /* move in back to %esi, toss from */
  526. "        movl    32(%%esp), %%ebpn"      /* ebp = lcode */
  527. "        jmp     .L_while_testn"
  528. ".L_copy_two:n"
  529. "        rep     movswn"
  530. "        movl    8(%%esp), %%esin"       /* move in back to %esi, toss from */
  531. "        movl    32(%%esp), %%ebpn"      /* ebp = lcode */
  532. "        jmp     .L_while_testn"
  533. ".align 32,0x90n"
  534. ".L_check_dist_one:n"
  535. "        cmpl    $1, %%ebpn"            /* if dist 1, is a memset */
  536. "        jne     .L_check_windown"
  537. "        cmpl    %%edi, 20(%%esp)n"
  538. "        je      .L_check_windown"      /* out == beg, if outside window */
  539. "        movl    64(%%esp), %%ecxn"      /* ecx = len */
  540. "        movb    -1(%%edi), %%aln"
  541. "        movb    %%al, %%ahn"
  542. "        sarl    %%ecxn"
  543. "        jnc     .L_set_twon"
  544. "        movb    %%al, (%%edi)n"
  545. "        incl    %%edin"
  546. ".L_set_two:n"
  547. "        rep     stoswn"
  548. "        movl    32(%%esp), %%ebpn"      /* ebp = lcode */
  549. "        jmp     .L_while_testn"
  550. ".align 32,0x90n"
  551. ".L_test_for_second_level_length:n"
  552. "        testb   $64, %%aln"
  553. "        jnz     .L_test_for_end_of_blockn" /* if ((op & 64) != 0) */
  554. "        xorl    %%eax, %%eaxn"
  555. "        incl    %%eaxn"
  556. "        shll    %%cl, %%eaxn"
  557. "        decl    %%eaxn"
  558. "        andl    %%edx, %%eaxn"         /* eax &= hold */
  559. "        addl    64(%%esp), %%eaxn"     /* eax += len */
  560. "        movl    (%%ebp,%%eax,4), %%eaxn" /* eax = lcode[val+(hold&mask[op])]*/
  561. "        jmp     .L_dolenn"
  562. ".align 32,0x90n"
  563. ".L_test_for_second_level_dist:n"
  564. "        testb   $64, %%aln"
  565. "        jnz     .L_invalid_distance_coden" /* if ((op & 64) != 0) */
  566. "        xorl    %%eax, %%eaxn"
  567. "        incl    %%eaxn"
  568. "        shll    %%cl, %%eaxn"
  569. "        decl    %%eaxn"
  570. "        andl    %%edx, %%eaxn"         /* eax &= hold */
  571. "        addl    %%ebp, %%eaxn"         /* eax += dist */
  572. "        movl    36(%%esp), %%ecxn"     /* ecx = dcode */
  573. "        movl    (%%ecx,%%eax,4), %%eaxn" /* eax = dcode[val+(hold&mask[op])]*/
  574. "        jmp     .L_dodistn"
  575. ".align 32,0x90n"
  576. ".L_clip_window:n"
  577. "        movl    %%eax, %%ecxn"
  578. "        movl    48(%%esp), %%eaxn"     /* eax = wsize */
  579. "        negl    %%ecxn"                /* nbytes = -nbytes */
  580. "        movl    28(%%esp), %%esin"     /* from = window */
  581. "        cmpl    %%ebp, %%eaxn"
  582. "        jb      .L_invalid_distance_too_farn" /* if (dist > wsize) */
  583. "        addl    %%ebp, %%ecxn"         /* nbytes = dist - nbytes */
  584. "        cmpl    $0, 52(%%esp)n"
  585. "        jne     .L_wrap_around_windown" /* if (write != 0) */
  586. "        subl    %%ecx, %%eaxn"
  587. "        addl    %%eax, %%esin"         /* from += wsize - nbytes */
  588. "        movl    64(%%esp), %%eaxn"     /* eax = len */
  589. "        cmpl    %%ecx, %%eaxn"
  590. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  591. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  592. "        rep     movsbn"
  593. "        movl    %%edi, %%esin"
  594. "        subl    %%ebp, %%esin"         /* from = out - dist */
  595. "        jmp     .L_do_copyn"
  596. ".align 32,0x90n"
  597. ".L_wrap_around_window:n"
  598. "        movl    52(%%esp), %%eaxn"     /* eax = write */
  599. "        cmpl    %%eax, %%ecxn"
  600. "        jbe     .L_contiguous_in_windown" /* if (write >= nbytes) */
  601. "        addl    48(%%esp), %%esin"     /* from += wsize */
  602. "        addl    %%eax, %%esin"         /* from += write */
  603. "        subl    %%ecx, %%esin"         /* from -= nbytes */
  604. "        subl    %%eax, %%ecxn"         /* nbytes -= write */
  605. "        movl    64(%%esp), %%eaxn"     /* eax = len */
  606. "        cmpl    %%ecx, %%eaxn"
  607. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  608. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  609. "        rep     movsbn"
  610. "        movl    28(%%esp), %%esin"     /* from = window */
  611. "        movl    52(%%esp), %%ecxn"     /* nbytes = write */
  612. "        cmpl    %%ecx, %%eaxn"
  613. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  614. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  615. "        rep     movsbn"
  616. "        movl    %%edi, %%esin"
  617. "        subl    %%ebp, %%esin"         /* from = out - dist */
  618. "        jmp     .L_do_copyn"
  619. ".align 32,0x90n"
  620. ".L_contiguous_in_window:n"
  621. "        addl    %%eax, %%esin"
  622. "        subl    %%ecx, %%esin"         /* from += write - nbytes */
  623. "        movl    64(%%esp), %%eaxn"     /* eax = len */
  624. "        cmpl    %%ecx, %%eaxn"
  625. "        jbe     .L_do_copyn"           /* if (nbytes >= len) */
  626. "        subl    %%ecx, %%eaxn"         /* len -= nbytes */
  627. "        rep     movsbn"
  628. "        movl    %%edi, %%esin"
  629. "        subl    %%ebp, %%esin"         /* from = out - dist */
  630. "        jmp     .L_do_copyn"           /* if (nbytes >= len) */
  631. ".align 32,0x90n"
  632. ".L_do_copy:n"
  633. "        movl    %%eax, %%ecxn"
  634. "        rep     movsbn"
  635. "        movl    8(%%esp), %%esin"      /* move in back to %esi, toss from */
  636. "        movl    32(%%esp), %%ebpn"     /* ebp = lcode */
  637. "        jmp     .L_while_testn"
  638. ".L_test_for_end_of_block:n"
  639. "        testb   $32, %%aln"
  640. "        jz      .L_invalid_literal_length_coden"
  641. "        movl    $1, 72(%%esp)n"
  642. "        jmp     .L_break_loop_with_statusn"
  643. ".L_invalid_literal_length_code:n"
  644. "        movl    $2, 72(%%esp)n"
  645. "        jmp     .L_break_loop_with_statusn"
  646. ".L_invalid_distance_code:n"
  647. "        movl    $3, 72(%%esp)n"
  648. "        jmp     .L_break_loop_with_statusn"
  649. ".L_invalid_distance_too_far:n"
  650. "        movl    8(%%esp), %%esin"
  651. "        movl    $4, 72(%%esp)n"
  652. "        jmp     .L_break_loop_with_statusn"
  653. ".L_break_loop:n"
  654. "        movl    $0, 72(%%esp)n"
  655. ".L_break_loop_with_status:n"
  656. /* put in, out, bits, and hold back into ar and pop esp */
  657. "        movl    %%esi, 8(%%esp)n"      /* save in */
  658. "        movl    %%edi, 16(%%esp)n"     /* save out */
  659. "        movl    %%ebx, 44(%%esp)n"     /* save bits */
  660. "        movl    %%edx, 40(%%esp)n"     /* save hold */
  661. "        movl    4(%%esp), %%ebpn"      /* restore esp, ebp */
  662. "        movl    (%%esp), %%espn"
  663.           :
  664.           : "m" (ar)
  665.           : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
  666.     );
  667. #elif defined( _MSC_VER ) && ! defined( _M_AMD64 )
  668.     __asm {
  669. lea eax, ar
  670. mov [eax], esp         /* save esp, ebp */
  671. mov [eax+4], ebp
  672. mov esp, eax
  673. mov esi, [esp+8]       /* esi = in */
  674. mov edi, [esp+16]      /* edi = out */
  675. mov edx, [esp+40]      /* edx = hold */
  676. mov ebx, [esp+44]      /* ebx = bits */
  677. mov ebp, [esp+32]      /* ebp = lcode */
  678. cld
  679. jmp L_do_loop
  680. ALIGN 4
  681. L_while_test:
  682. cmp [esp+24], edi
  683. jbe L_break_loop
  684. cmp [esp+12], esi
  685. jbe L_break_loop
  686. L_do_loop:
  687. cmp bl, 15
  688. ja L_get_length_code    /* if (15 < bits) */
  689. xor eax, eax
  690. lodsw                         /* al = *(ushort *)in++ */
  691. mov cl, bl            /* cl = bits, needs it for shifting */
  692. add bl, 16             /* bits += 16 */
  693. shl eax, cl
  694. or edx, eax        /* hold |= *((ushort *)in)++ << bits */
  695. L_get_length_code:
  696. mov eax, [esp+56]      /* eax = lmask */
  697. and eax, edx          /* eax &= hold */
  698. mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
  699. L_dolen:
  700. mov cl, ah            /* cl = this.bits */
  701. sub bl, ah            /* bits -= this.bits */
  702. shr edx, cl           /* hold >>= this.bits */
  703. test al, al
  704. jnz L_test_for_length_base /* if (op != 0) 45.7% */
  705. shr eax, 16            /* output this.val char */
  706. stosb
  707. jmp L_while_test
  708. ALIGN 4
  709. L_test_for_length_base:
  710. mov ecx, eax          /* len = this */
  711. shr ecx, 16            /* len = this.val */
  712. mov [esp+64], ecx      /* save len */
  713. mov cl, al
  714. test al, 16
  715. jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
  716. and cl, 15             /* op &= 15 */
  717. jz L_decode_distance    /* if (!op) */
  718. cmp bl, cl
  719. jae L_add_bits_to_len    /* if (op <= bits) */
  720. mov ch, cl            /* stash op in ch, freeing cl */
  721. xor eax, eax
  722. lodsw                         /* al = *(ushort *)in++ */
  723. mov cl, bl            /* cl = bits, needs it for shifting */
  724. add bl, 16             /* bits += 16 */
  725. shl eax, cl
  726. or edx, eax         /* hold |= *((ushort *)in)++ << bits */
  727. mov cl, ch            /* move op back to ecx */
  728. L_add_bits_to_len:
  729. sub bl, cl
  730. xor eax, eax
  731. inc eax
  732. shl eax, cl
  733. dec eax
  734. and eax, edx          /* eax &= hold */
  735. shr edx, cl
  736. add [esp+64], eax      /* len += hold & mask[op] */
  737. L_decode_distance:
  738. cmp bl, 15
  739. ja L_get_distance_code  /* if (15 < bits) */
  740. xor eax, eax
  741. lodsw                         /* al = *(ushort *)in++ */
  742. mov cl, bl            /* cl = bits, needs it for shifting */
  743. add bl, 16             /* bits += 16 */
  744. shl eax, cl
  745. or edx, eax         /* hold |= *((ushort *)in)++ << bits */
  746. L_get_distance_code:
  747. mov eax, [esp+60]      /* eax = dmask */
  748. mov ecx, [esp+36]      /* ecx = dcode */
  749. and eax, edx          /* eax &= hold */
  750. mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
  751. L_dodist:
  752. mov ebp, eax          /* dist = this */
  753. shr ebp, 16            /* dist = this.val */
  754. mov cl, ah
  755. sub bl, ah            /* bits -= this.bits */
  756. shr edx, cl           /* hold >>= this.bits */
  757. mov cl, al            /* cl = this.op */
  758. test al, 16             /* if ((op & 16) == 0) */
  759. jz L_test_for_second_level_dist
  760. and cl, 15             /* op &= 15 */
  761. jz L_check_dist_one
  762. cmp bl, cl
  763. jae L_add_bits_to_dist   /* if (op <= bits) 97.6% */
  764. mov ch, cl            /* stash op in ch, freeing cl */
  765. xor eax, eax
  766. lodsw                         /* al = *(ushort *)in++ */
  767. mov cl, bl            /* cl = bits, needs it for shifting */
  768. add bl, 16             /* bits += 16 */
  769. shl eax, cl
  770. or edx, eax        /* hold |= *((ushort *)in)++ << bits */
  771. mov cl, ch            /* move op back to ecx */
  772. L_add_bits_to_dist:
  773. sub bl, cl
  774. xor eax, eax
  775. inc eax
  776. shl eax, cl
  777. dec eax                 /* (1 << op) - 1 */
  778. and eax, edx          /* eax &= hold */
  779. shr edx, cl
  780. add ebp, eax          /* dist += hold & ((1 << op) - 1) */
  781. L_check_window:
  782. mov [esp+8], esi       /* save in so from can use it's reg */
  783. mov eax, edi
  784. sub eax, [esp+20]      /* nbytes = out - beg */
  785. cmp eax, ebp
  786. jb L_clip_window        /* if (dist > nbytes) 4.2% */
  787. mov ecx, [esp+64]      /* ecx = len */
  788. mov esi, edi
  789. sub esi, ebp          /* from = out - dist */
  790. sar ecx, 1
  791. jnc L_copy_two
  792. rep     movsw
  793. mov al, [esi]
  794. mov [edi], al
  795. inc edi
  796. mov esi, [esp+8]      /* move in back to %esi, toss from */
  797. mov ebp, [esp+32]     /* ebp = lcode */
  798. jmp L_while_test
  799. L_copy_two:
  800. rep     movsw
  801. mov esi, [esp+8]      /* move in back to %esi, toss from */
  802. mov ebp, [esp+32]     /* ebp = lcode */
  803. jmp L_while_test
  804. ALIGN 4
  805. L_check_dist_one:
  806. cmp ebp, 1            /* if dist 1, is a memset */
  807. jne L_check_window
  808. cmp [esp+20], edi
  809. je L_check_window    /* out == beg, if outside window */
  810. mov ecx, [esp+64]     /* ecx = len */
  811. mov al, [edi-1]
  812. mov ah, al
  813. sar ecx, 1
  814. jnc L_set_two
  815. mov [edi], al         /* memset out with from[-1] */
  816. inc edi
  817. L_set_two:
  818. rep     stosw
  819. mov ebp, [esp+32]     /* ebp = lcode */
  820. jmp L_while_test
  821. ALIGN 4
  822. L_test_for_second_level_length:
  823. test al, 64
  824. jnz L_test_for_end_of_block /* if ((op & 64) != 0) */
  825. xor eax, eax
  826. inc eax
  827. shl eax, cl
  828. dec eax
  829. and eax, edx         /* eax &= hold */
  830. add eax, [esp+64]     /* eax += len */
  831. mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
  832. jmp L_dolen
  833. ALIGN 4
  834. L_test_for_second_level_dist:
  835. test al, 64
  836. jnz L_invalid_distance_code /* if ((op & 64) != 0) */
  837. xor eax, eax
  838. inc eax
  839. shl eax, cl
  840. dec eax
  841. and eax, edx         /* eax &= hold */
  842. add eax, ebp         /* eax += dist */
  843. mov ecx, [esp+36]     /* ecx = dcode */
  844. mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
  845. jmp L_dodist
  846. ALIGN 4
  847. L_clip_window:
  848. mov ecx, eax
  849. mov eax, [esp+48]     /* eax = wsize */
  850. neg ecx                /* nbytes = -nbytes */
  851. mov esi, [esp+28]     /* from = window */
  852. cmp eax, ebp
  853. jb L_invalid_distance_too_far /* if (dist > wsize) */
  854. add ecx, ebp         /* nbytes = dist - nbytes */
  855. cmp dword ptr [esp+52], 0
  856. jne L_wrap_around_window /* if (write != 0) */
  857. sub eax, ecx
  858. add esi, eax         /* from += wsize - nbytes */
  859. mov eax, [esp+64]    /* eax = len */
  860. cmp eax, ecx
  861. jbe L_do_copy          /* if (nbytes >= len) */
  862. sub eax, ecx         /* len -= nbytes */
  863. rep     movsb
  864. mov esi, edi
  865. sub esi, ebp         /* from = out - dist */
  866. jmp L_do_copy
  867. ALIGN 4
  868. L_wrap_around_window:
  869. mov eax, [esp+52]    /* eax = write */
  870. cmp ecx, eax
  871. jbe L_contiguous_in_window /* if (write >= nbytes) */
  872. add esi, [esp+48]    /* from += wsize */
  873. add esi, eax         /* from += write */
  874. sub esi, ecx         /* from -= nbytes */
  875. sub ecx, eax         /* nbytes -= write */
  876. mov eax, [esp+64]    /* eax = len */
  877. cmp eax, ecx
  878. jbe L_do_copy          /* if (nbytes >= len) */
  879. sub eax, ecx         /* len -= nbytes */
  880. rep     movsb
  881. mov esi, [esp+28]     /* from = window */
  882. mov ecx, [esp+52]     /* nbytes = write */
  883. cmp eax, ecx
  884. jbe L_do_copy          /* if (nbytes >= len) */
  885. sub eax, ecx         /* len -= nbytes */
  886. rep     movsb
  887. mov esi, edi
  888. sub esi, ebp         /* from = out - dist */
  889. jmp L_do_copy
  890. ALIGN 4
  891. L_contiguous_in_window:
  892. add esi, eax
  893. sub esi, ecx         /* from += write - nbytes */
  894. mov eax, [esp+64]    /* eax = len */
  895. cmp eax, ecx
  896. jbe L_do_copy          /* if (nbytes >= len) */
  897. sub eax, ecx         /* len -= nbytes */
  898. rep     movsb
  899. mov esi, edi
  900. sub esi, ebp         /* from = out - dist */
  901. jmp L_do_copy
  902. ALIGN 4
  903. L_do_copy:
  904. mov ecx, eax
  905. rep     movsb
  906. mov esi, [esp+8]      /* move in back to %esi, toss from */
  907. mov ebp, [esp+32]     /* ebp = lcode */
  908. jmp L_while_test
  909. L_test_for_end_of_block:
  910. test al, 32
  911. jz L_invalid_literal_length_code
  912. mov dword ptr [esp+72], 1
  913. jmp L_break_loop_with_status
  914. L_invalid_literal_length_code:
  915. mov dword ptr [esp+72], 2
  916. jmp L_break_loop_with_status
  917. L_invalid_distance_code:
  918. mov dword ptr [esp+72], 3
  919. jmp L_break_loop_with_status
  920. L_invalid_distance_too_far:
  921. mov esi, [esp+4]
  922. mov dword ptr [esp+72], 4
  923. jmp L_break_loop_with_status
  924. L_break_loop:
  925. mov dword ptr [esp+72], 0
  926. L_break_loop_with_status:
  927. /* put in, out, bits, and hold back into ar and pop esp */
  928. mov [esp+8], esi     /* save in */
  929. mov [esp+16], edi    /* save out */
  930. mov [esp+44], ebx    /* save bits */
  931. mov [esp+40], edx    /* save hold */
  932. mov ebp, [esp+4]     /* restore esp, ebp */
  933. mov esp, [esp]
  934.     }
  935. #else
  936. #error "x86 architecture not defined"
  937. #endif
  938.     if (ar.status > 1) {
  939.         if (ar.status == 2)
  940.             strm->msg = "invalid literal/length code";
  941.         else if (ar.status == 3)
  942.             strm->msg = "invalid distance code";
  943.         else
  944.             strm->msg = "invalid distance too far back";
  945.         state->mode = BAD;
  946.     }
  947.     else if ( ar.status == 1 ) {
  948.         state->mode = TYPE;
  949.     }
  950.     /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
  951.     ar.len = ar.bits >> 3;
  952.     ar.in -= ar.len;
  953.     ar.bits -= ar.len << 3;
  954.     ar.hold &= (1U << ar.bits) - 1;
  955.     /* update state and return */
  956.     strm->next_in = ar.in;
  957.     strm->next_out = ar.out;
  958.     strm->avail_in = (unsigned)(ar.in < ar.last ?
  959.                                 PAD_AVAIL_IN + (ar.last - ar.in) :
  960.                                 PAD_AVAIL_IN - (ar.in - ar.last));
  961.     strm->avail_out = (unsigned)(ar.out < ar.end ?
  962.                                  PAD_AVAIL_OUT + (ar.end - ar.out) :
  963.                                  PAD_AVAIL_OUT - (ar.out - ar.end));
  964.     state->hold = ar.hold;
  965.     state->bits = ar.bits;
  966.     return;
  967. }