// File: /workspace/github_c_makefile_star2_O2/snej[P]zdelta/inffast.c
// Function: inflate_fast
int inflate_fast(bl, bd, bzd, tl, td, tzd, s, z)
uInt bl, bd, bzd;
inflate_huft *tl;
inflate_huft *td;
inflate_huft *tzd; /* need separate declaration for Borland C++ */
inflate_blocks_statef *s;
zd_streamp z;
{
  inflate_huft *t;      /* temporary pointer */
  uInt e;               /* extra bits or operation */
  uLong b;              /* bit buffer */
  uInt k;               /* bits in bit buffer */
  Bytef *p;             /* input data pointer */
  uInt n;               /* bytes available there */
  Bytef *q;             /* output window write pointer */
  uInt m;               /* bytes to end of window or read pointer */
  uInt ml;              /* mask for literal/length tree */
  uInt md;              /* mask for distance tree */
  uInt mzd;             /* mask for zdelta code tree */
  uInt c;               /* bytes to copy */
  uInt d;               /* distance back to copy from */
  Bytef *r;             /* copy source pointer */

  /* zdelta local variables, needed to handle the reference window ptrs */
  uInt sign;
  uInt best_ptr;
  ulg ptr;
  ulg *rwptr = s->rwptr;         /* zdelta: reference window ptr */
  /* uInt zd_bcode; */                /* zdelta: byte code */
  /* load input, output, bit values */
  LOAD

  /* initialize masks */
  ml = inflate_mask[bl];
  md = inflate_mask[bd];
  mzd = inflate_mask[bzd];

  /* do until not enough input or output space for fast loop */
  do {                          /* assume called with m >= 258 && n >= 10 */
    /* get literal/distance code */
    GRABBITS(15) /* max bits for literal/distance code */
    if ((e = (t = td + ((uInt)b & md))->exop) == 0)
    {
      Assert(t->bits <= k, "dumping too many bits (literal)");
      DUMPBITS(t->bits)
      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
                "inflate:        * literal '%c'\n" :
                "inflate:        * literal 0x%02x\n", t->base));
      /* output the literal here */
      *q++ = (Byte)t->base;
      TraceHuf( (stderr, "d:%u\n", t->base) );
      m--;
      continue;
    }
    do {
      Assert(t->bits <= k, "dumping too many bits (dist)");
      DUMPBITS(t->bits)
      if (e & 16)
      {
	e &= 15;
	GRABBITS(e) /* get extra bits for distance (up to 13) */
	d = t->base + ((uInt)b & inflate_mask[e]);
	Assert(e <= k, "dumping too many bits (dist extra)");
	DUMPBITS(e)
        Tracevv((stderr, "inflate:         * distance %u\n", c));

        /* decode length base of block to copy */
        GRABBITS(24);           /* max bits for length code and extra */
        e = (t = tl + ((uInt)b & ml))->exop;
        do {
	  Assert(t->bits <= k, "dumping too many bits (len)");
          DUMPBITS(t->bits)
          if (e & 16)
          {
            /* get extra bits to add to distance base */
            e &= 15;
            c = t->base + ((uInt)b & inflate_mask[e]);
	    Assert(e <= k, "dumping too many bits (len extra)");
            DUMPBITS(e)
            Tracevv((stderr, "inflate:         * length %u\n", d));

	    if( c & REFMATCH ) {             /* if reference copy          */
	      sign = (c >> 8) & ZD_MINUS;    /* get distance sign          */
	      c   &= (REFMATCH-1);
	      
	      GRABBITS(15)                  /* max bits for ZDELTA flag code */
	      e = (t = tzd + ((uInt)b & mzd))->exop;
	      do{
		Assert(t->bits <= k, "dumping too many bits (zdelta)");
		DUMPBITS(t->bits);
		if(e == 0){
		  best_ptr = (Byte)t->base;  /* get reference pointer      */

		  /* jump to the beginning of the copy */
                  if(ZD_PLUS == sign) {
                    ptr = rwptr[best_ptr] + d;
                  } else {
                    ptr = rwptr[best_ptr] - d;
                  }

		  /* do the copy */
		  memcpy(q,z->base[best_ptr/2]+ptr,c);
		  q += c;                    /* update pointers            */
		  m -= c;   /* update the number of available output bytes */

		  if(d > ZD_FAR){ 	     /* update reference pointers  */
		    if(s->stable[best_ptr])
		      s->stable[best_ptr] = 0;
		    else
		      rwptr[best_ptr] = ptr + c;
		  }
		  else{
		    s->stable[best_ptr] = 1;
		    rwptr[best_ptr] = ptr + c;
		  }
		  break;
		}
		if( (e & 64) == 0 ){
		  t += t->base;
		  e = (t += ((uInt)b & inflate_mask[e]))->exop;
		}
		else{
		  z->msg = (char*)"invalid zdelta code";
		  UNGRAB
		  UPDATE
		  return ZD_DATA_ERROR;
		}
	      } while(1); /* zdelta code */
	    }
	    else{
	      m -= c;    /* update the number of available output bytes     */
	      if ((uInt)(q - s->window) >= d)   /*    offset before dest    */
	      {                                 /*    just copy             */
		r = q - d;
		*q++ = *r++;  c--;              /* minimum count is three,  */
		*q++ = *r++;  c--;              /* so unroll loop a little  */
	      }
	      else                        /* else offset after destination  */
	      {
		e = d - (uInt)(q - s->window);  /* bytes from offset to end */
		r = s->end - e;                 /* pointer to offset        */
		if (c > e)                      /* if source crosses,       */
		{	
		  c -= e;                       /* copy to end of window    */
		  do {
		    *q++ = *r++;
		  } while (--e);
		  r = s->window;          /* copy rest from start of window */
		}
	      }
	      do {                              /* copy all or what's left  */
		*q++ = *r++;
	      } while (--c);
	    }
	    break;
          }
          else if ((e & 64) == 0)
	  {
	    t += t->base;
	    e = (t += ((uInt)b & inflate_mask[e]))->exop;
	  }
          else
	  {
	    z->msg = (char*)"invalid length code";
	    UNGRAB
	    UPDATE
	    return ZD_DATA_ERROR;
          }
        } while (1);                                        /* length code */
        break;
      }
      if ((e & 64) == 0)
      {
	t += t->base;
	if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
        {
	  DUMPBITS(t->bits)
	  Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
		   "inflate:         * literal '%c'\n" :
		   "inflate:         * literal 0x%02x\n", t->base));
	  *q++ = (Byte)t->base;
	  m--;
	  break;
	}
      }
      else if (e & 32)
      {
	Tracevv((stderr, "inflate:         * end of block\n"));
	UNGRAB
        UPDATE
	return ZD_STREAM_END;
      }
      else
      {
	z->msg = (char*)"invalid literal/distance code";
	UNGRAB
        UPDATE
	return ZD_DATA_ERROR;
      }
    } while (1);                                          /* distance code */
/* zdelta: maximum match length is 1026 
 * } while (m >= 258 && n >= 10); 
 */
  } while (m >= MAX_MATCH && n >= 10); 
  /* not enough input or output--restore pointers and return */
  UNGRAB
  UPDATE
  return ZD_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r8, 0x50(%rsp)
movq %rcx, 0x48(%rsp)
movq 0x98(%rsp), %r10
movq 0x90(%rsp), %r11
movq 0x58(%r11), %rbx
movq 0x50(%r11), %rcx
cmpq %rcx, %rbx
jae 0x7bf0
movq %rbx, %rax
notq %rax
addq %rax, %rcx
jmp 0x7bf7
movq 0x48(%r11), %rcx
subq %rbx, %rcx
movq (%r10), %r15
movl 0x8(%r10), %r12d
movq 0x30(%r11), %rbp
movl 0x2c(%r11), %r13d
movl %edi, %eax
leaq 0x8591(%rip), %r14      # 0x101a0
movl (%r14,%rax,4), %eax
movl %eax, 0x24(%rsp)
movl %esi, %eax
movl (%r14,%rax,4), %esi
movl %edx, %eax
movl (%r14,%rax,4), %eax
movl %eax, 0x20(%rsp)
movl %esi, 0x4(%rsp)
movq %rcx, 0x8(%rsp)
movl %r13d, %r13d
cmpq $0xe, %r13
ja 0x7c52
movzbl (%r15), %eax
movl %r13d, %ecx
shlq %cl, %rax
decl %r12d
incq %r15
orq %rax, %rbp
addq $0x8, %r13
jmp 0x7c33
movl %esi, %eax
andl %ebp, %eax
movq 0x50(%rsp), %rcx
leaq (%rcx,%rax,8), %rdi
movb (%rdi), %r8b
testb %r8b, %r8b
je 0x7cc7
movl %r13d, %edx
movzbl 0x1(%rdi), %eax
movl %eax, %ecx
shrq %cl, %rbp
movzbl %r8b, %esi
subl %eax, %edx
testb $0x10, %sil
jne 0x7ce5
testb $0x40, %r8b
jne 0x7f9a
movl 0x4(%rdi), %eax
leaq (%rdi,%rax,8), %rax
movl %esi, %ecx
movl (%r14,%rcx,4), %ecx
andl %ebp, %ecx
leaq (%rax,%rcx,8), %rdi
movb (%rdi), %r8b
movl %edx, %r13d
testb %r8b, %r8b
jne 0x7c6a
movzbl 0x1(%rdi), %ecx
shrq %cl, %rbp
subl %ecx, %edx
movb 0x4(%rdi), %al
movb %al, (%rbx)
incq %rbx
movq 0x8(%rsp), %rcx
decl %ecx
movl %edx, %r13d
jmp 0x7f69
movzbl 0x1(%rdi), %ecx
shrq %cl, %rbp
subl %ecx, %r13d
movb 0x4(%rdi), %al
movb %al, (%rbx)
incq %rbx
movq 0x8(%rsp), %rcx
decl %ecx
jmp 0x7f6d
andl $0xf, %esi
movl %edx, %edx
addl %esi, %eax
subl %r13d, %eax
cmpq %rsi, %rdx
jae 0x7d0f
decl %r12d
movzbl (%r15), %r8d
movl %edx, %ecx
shlq %cl, %r8
incq %r15
orq %r8, %rbp
addq $0x8, %rdx
addl $-0x8, %eax
jmp 0x7cef
movl 0x4(%rdi), %edi
movl (%r14,%rsi,4), %r8d
andl %ebp, %r8d
movl %esi, %ecx
shrq %cl, %rbp
subl %esi, %edx
cmpq $0x17, %rdx
ja 0x7d41
decl %r12d
movzbl (%r15), %esi
movl %edx, %ecx
shlq %cl, %rsi
incq %r15
orq %rsi, %rbp
addq $0x8, %rdx
addl $-0x8, %eax
jmp 0x7d20
addl %edi, %r8d
negl %eax
movl 0x24(%rsp), %ecx
andl %ebp, %ecx
movq 0x48(%rsp), %rdx
movl %eax, %r13d
movl %ecx, %eax
leaq (%rdx,%rax,8), %rdx
movzbl 0x1(%rdx), %eax
movl %eax, %ecx
shrq %cl, %rbp
movzbl (%rdx), %ecx
subl %eax, %r13d
testb $0x10, %cl
jne 0x7d88
testb $0x40, %cl
jne 0x7fa9
movl 0x4(%rdx), %eax
leaq (%rdx,%rax,8), %rdx
movl %ecx, %eax
movl (%r14,%rax,4), %ecx
andl %ebp, %ecx
jmp 0x7d54
andl $0xf, %ecx
movl %ecx, %eax
movl (%r14,%rax,4), %eax
andl %ebp, %eax
addl 0x4(%rdx), %eax
shrq %cl, %rbp
subl %ecx, %r13d
btl $0xe, %eax
movl %r8d, %edx
jb 0x7de7
movl 0x40(%r11), %ecx
movl %ebx, %esi
subl %ecx, %esi
subl %esi, %r8d
jbe 0x7eeb
movq 0x48(%r11), %rcx
subq %r8, %rcx
cmpl %r8d, %eax
jbe 0x7f40
xorl %esi, %esi
movb (%rcx,%rsi), %dl
movb %dl, (%rbx,%rsi)
incq %rsi
cmpl %esi, %r8d
jne 0x7dc8
movl %eax, %edx
subl %r8d, %edx
movq 0x40(%r11), %rcx
addq %rsi, %rbx
jmp 0x7f42
movl %r13d, %r13d
cmpq $0xe, %r13
ja 0x7e09
movzbl (%r15), %esi
movl %r13d, %ecx
shlq %cl, %rsi
decl %r12d
incq %r15
orq %rsi, %rbp
addq $0x8, %r13
jmp 0x7dea
movq %r9, %rsi
movl %eax, %ecx
andl $0x3fff, %ecx           # imm = 0x3FFF
movl %ecx, 0x14(%rsp)
movl 0x20(%rsp), %ecx
andl %ebp, %ecx
movl %ecx, %ecx
leaq (%rsi,%rcx,8), %rsi
movzbl 0x1(%rsi), %ecx
shrq %cl, %rbp
movzbl (%rsi), %edi
subl %ecx, %r13d
testq %rdi, %rdi
je 0x7e4d
testb $0x40, %dil
jne 0x7fb9
movl 0x4(%rsi), %ecx
leaq (%rsi,%rcx,8), %rsi
movl (%r14,%rdi,4), %ecx
jmp 0x7e1c
movq %r9, 0x18(%rsp)
movl 0x4(%rsi), %ecx
movzbl %cl, %esi
movq %rdx, %rdi
negq %rdi
testw %ax, %ax
movq %rsi, 0x30(%rsp)
movl %esi, %eax
cmovnsq %rdx, %rdi
addq 0x70(%r11,%rax,8), %rdi
andl $0xfe, %ecx
movq 0x30(%r10,%rcx,4), %rsi
movq %rdi, 0x28(%rsp)
addq %rdi, %rsi
movl 0x14(%rsp), %edx
movq %rdx, 0x38(%rsp)
movq %rbx, %rdi
movq %r8, 0x40(%rsp)
callq 0x10f0
movq 0x38(%rsp), %rdi
addq %rdi, %rbx
movq 0x8(%rsp), %rcx
subl 0x14(%rsp), %ecx
cmpl $0x101, 0x40(%rsp)      # imm = 0x101
jb 0x7f08
movq 0x28(%rsp), %rdx
movq 0x30(%rsp), %rax
movq 0x90(%rsp), %rsi
cmpq $0x0, 0x80(%rsi,%rax,8)
movq %rsi, %r11
movl 0x4(%rsp), %esi
je 0x7f83
andq $0x0, 0x80(%r11,%rax,8)
jmp 0x7f8b
movq %rbx, %rcx
subq %rdx, %rcx
movb (%rcx), %dl
movb %dl, (%rbx)
movb 0x1(%rcx), %dl
addq $0x2, %rcx
movb %dl, 0x1(%rbx)
addq $0x2, %rbx
leal -0x2(%rax), %edx
jmp 0x7f42
movq 0x30(%rsp), %rax
movq 0x90(%rsp), %rsi
movq $0x1, 0x80(%rsi,%rax,8)
movq 0x28(%rsp), %rdx
addq %rdi, %rdx
movq %rdx, 0x70(%rsi,%rax,8)
movq %rsi, %r11
movq 0x98(%rsp), %r10
movq 0x18(%rsp), %r9
jmp 0x7f69
movl %eax, %edx
movq 0x8(%rsp), %rsi
subl %eax, %esi
movq %rsi, 0x8(%rsp)
movl %edx, %eax
xorl %edx, %edx
movb (%rcx,%rdx), %sil
movb %sil, (%rbx,%rdx)
incq %rdx
cmpl %edx, %eax
jne 0x7f52
addq %rdx, %rbx
movq 0x8(%rsp), %rcx
movl 0x4(%rsp), %esi
xorl %eax, %eax
cmpl $0x1002, %ecx           # imm = 0x1002
jb 0x7fcd
cmpl $0x9, %r12d
ja 0x7c2b
jmp 0x7fcd
addq %rdi, %rdx
movq %rdx, 0x70(%r11,%rax,8)
movq 0x98(%rsp), %r10
movq 0x18(%rsp), %r9
jmp 0x7f6d
testb $0x20, %r8b
jne 0x7fb5
leaq 0x2177(%rip), %rax      # 0xa11e
jmp 0x7fc3
leaq 0x215a(%rip), %rax      # 0xa10a
movl %r13d, %edx
jmp 0x7fc3
pushq $0x1
jmp 0x7fc9
movl %r13d, %edx
leaq 0x2133(%rip), %rax      # 0xa0f6
movq %rax, 0x50(%r10)
pushq $-0x3
popq %rax
movl %edx, %r13d
movl 0x8(%r10), %ecx
subl %r12d, %ecx
movl %r13d, %edx
shrl $0x3, %edx
cmpl %ecx, %edx
cmovael %ecx, %edx
addl %edx, %r12d
subq %rdx, %r15
shll $0x3, %edx
subl %edx, %r13d
movq %rbp, 0x30(%r11)
movl %r13d, 0x2c(%r11)
movl %r12d, 0x8(%r10)
movq %r15, %rcx
subq (%r10), %rcx
addq %rcx, 0x10(%r10)
movq %r15, (%r10)
movq %rbx, 0x58(%r11)
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop