// File: /workspace/github_c_makefile_star2_O2/snej[P]zdelta/deflate.c
// Function: reference_longest_match
local void reference_longest_match(s, cur_match, rw)
     deflate_state *s;
     IPos cur_match;
     int rw;
{
  register Bytef *scan = s->window + s->strstart; /* current string */
  register Bytef *match;                          /* matched string */
  register uInt len;                              /* length of current match */
  register int  benefit;
  register int  strategy = s->strategy; /* expected length for literal codes */
  /* max hash chain length, we want to search in the reference data
   * no longer than in the target data
   */
  register uInt chain_length = s->max_chain_length;

  uInt cur_distance;	       /* the shortest distance to the current match */
  int  cur_ptr;  

  long min;                    /* value of the smaller ref pointer */ 
  long max;                    /* value of the greater ref pointer */ 
  long mid;                   
 
  int min_ptr;
  int max_ptr;

  uInt best_len      = s->match_length;   /* best match length so far   */
  uInt best_distance = s->match_distance; /* best match distance so far */
  int best_benefit   = s->match_benefit;

  uInt nice_match    = s->nice_match;     /* stop if match long enough */
  int best_ptr       = NO_PTR;
  Pos best_match     = 0;

  Pos limit;
    
  Pos *prev  = s->ref_prev[rw];
  uInt wmask = s->rw_mask;
  ulg  wsize =  s->ref_window_size[rw];  

  register Bytef *strend   = s->window + s->strstart + MAX_MATCH;
  register Byte scan_end1  = scan[best_len-1];

  /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
   * It is easy to get rid of this optimization if necessary.
   */

  /* set the search boundaries in the reference data window */
  if(s->rwptr[2*rw] < s->rwptr[2*rw+1]){
    min = s->rwptr[2*rw], max = s->rwptr[2*rw+1];
    min_ptr = 2*rw, max_ptr = 2*rw+1;
  }
  else{
    min = s->rwptr[2*rw+1], max = s->rwptr[2*rw];
    min_ptr = 2*rw+1, max_ptr = 2*rw;
  }
  mid = min >= 0 ? (max + min) / 2 : 0;
  
  limit = min >  ZD_UNREACHABLE ? (Pos) (min - ZD_UNREACHABLE) : NIL;
  while(cur_match > (IPos) max + ZD_UNREACHABLE) 
    cur_match = prev[cur_match & wmask];
  if(cur_match == NIL) return;
  
  /* Do not waste too much time if we already have a good match: */
  if (best_len >= s->good_match) {
    chain_length >>= 2;
  }
  /* Do not look for matches beyond the end of the input. This is necessary
   * to make deflate deterministic.
   */
  if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

  do {
    match = s->ref_window[rw] + cur_match; 
    
    /* Skip to next match if the match length cannot increase
     * or if the match length is less than 2:
     */
    if ( match[best_len-1] != scan_end1 ||
	 *match            != *scan     ||
	 *++match          != scan[1])      continue;
    
    /* check if the potential match is accessible */
    if((IPos) mid <= cur_match){
      cur_ptr = max_ptr;
      cur_distance = ZD_DISTANCE((IPos)max,cur_match);
    }
    else{ /* min_ptr is closer */
      cur_ptr = min_ptr;
      cur_distance = ZD_DISTANCE((IPos)min,cur_match);
    }
    if(cur_distance >= ZD_UNREACHABLE) continue;
    
    /* The check at best_len-1 can be removed because it will be made
     * again later. (This heuristic is not always a win.)
     * It is not necessary to compare scan[2] and match[2] since they
     * are always equal when the other bytes match, given that
     * the hash keys are equal and that HASH_BITS >= 8.
     */
    scan += 2, match++;
    Assert(*scan == *match, "ref. match[2]?");

    /* We check for insufficient lookahead only every 8th comparison;
     * the 256th check will be made at strstart+258.
     */
    do {
    } while (*++scan == *++match && *++scan == *++match &&
	     *++scan == *++match && *++scan == *++match &&
	     *++scan == *++match && *++scan == *++match &&
	     *++scan == *++match && *++scan == *++match &&
	     scan < strend);
    
    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");

    len     = MAX_MATCH - (int)(strend - scan);
    scan    = strend - MAX_MATCH;

    /* Do not look for matches beyond the end of the input. This is necessary
     * to make deflate deterministic.
     */
    if (len > s->lookahead) { len = s->lookahead; }
    if (len > wsize - cur_match) { len = wsize - cur_match; }
    GetBenefit(len, cur_distance);

    if( (benefit > best_benefit) || \
	(benefit == best_benefit && cur_distance < best_distance) ){

      best_match    = cur_match;
      best_distance = cur_distance; 
      best_ptr      = cur_ptr;
      best_len      = len;
      best_benefit  = benefit;
      if (len >= nice_match) break;
      scan_end1     = scan[best_len-1];

    }
    
  } while ((cur_match = prev[cur_match & wmask]) > limit &&
	   --chain_length);
  
  if(best_ptr != NO_PTR){
    s->match_ptr      = best_ptr;
    s->match_length   = best_len;
    s->match_distance = best_distance;
    s->match_start    = best_match;
    s->match_sign     = (best_match < s->rwptr[best_ptr] ? ZD_MINUS:ZD_PLUS);
    s->match_benefit  = best_benefit;
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq 0x48(%rdi), %rcx
movl 0xb4(%rdi), %r11d
leaq (%rcx,%r11), %r8
movl 0xf8(%rdi), %eax
movl %eax, -0x4c(%rsp)
movl 0xa8(%rdi), %r14d
movslq %edx, %r13
leal -0x1(%r14), %eax
leal (%r13,%r13), %edx
movl %edx, -0x44(%rsp)
movslq %edx, %rdx
movq 0x1a78(%rdi,%rdx,8), %r15
leal 0x1(%r13,%r13), %edx
movl %edx, -0x48(%rsp)
movslq %edx, %rdx
movq 0x1a78(%rdi,%rdx,8), %r12
cmpq %r12, %r15
movq %r12, %rdx
cmovlq %r15, %rdx
movb (%rax,%r8), %r10b
movq %r12, %rax
cmovgq %r15, %rax
movq %rax, -0x30(%rsp)
movl 0xec(%rdi), %ebp
movl 0xd0(%rdi), %eax
movl %eax, -0x70(%rsp)
movl 0xe0(%rdi), %eax
movl %eax, -0x74(%rsp)
movl 0x100(%rdi), %eax
movl %eax, -0x68(%rsp)
movq 0x60(%rdi,%r13,8), %rax
movq %rax, -0x18(%rsp)
movq 0x70(%rdi,%r13,8), %rbx
movq %rdi, -0x40(%rsp)
movl 0x44(%rdi), %r9d
movq %rdx, -0x58(%rsp)
testq %rdx, %rdx
js 0x3786
leaq (%r12,%r15), %rax
movabsq $0x2, %rdi
cqto
idivq %rdi
movq %rax, -0x38(%rsp)
jmp 0x378f
movq $0x0, -0x38(%rsp)
leaq (%rcx,%r11), %rax
addq $0x1002, %rax           # imm = 0x1002
movq %rax, -0x20(%rsp)
movzwl -0x58(%rsp), %edx
movq -0x30(%rsp), %rax
addl $0x8000, %eax           # imm = 0x8000
cmpl %eax, %esi
jbe 0x37ba
andl %r9d, %esi
movzwl (%rbx,%rsi,2), %esi
jmp 0x37ad
testl %esi, %esi
je 0x3a6f
movq %r12, -0x10(%rsp)
movq %r15, -0x8(%rsp)
xorl $0x8000, %edx           # imm = 0x8000
movl %ebp, %r11d
shrl $0x2, %r11d
movq -0x40(%rsp), %rax
cmpl 0xfc(%rax), %r14d
cmovbl %ebp, %r11d
movl 0xbc(%rax), %edi
movl -0x68(%rsp), %ecx
cmpl %edi, %ecx
movl %edi, -0x50(%rsp)
cmovael %edi, %ecx
movl %ecx, -0x68(%rsp)
xorl %edi, %edi
cmpq $0x8001, -0x58(%rsp)    # imm = 0x8001
movl $0x0, %ecx
movq %rcx, -0x60(%rsp)
cmovll %edi, %edx
movq 0x50(%rax,%r13,8), %rbp
leaq 0xa(%rbp), %rax
movq %rax, -0x28(%rsp)
movl $0x3, %eax
movl %eax, -0x6c(%rsp)
movl %esi, %esi
leaq (%rsi,%rbp), %rax
leal -0x1(%r14), %ecx
cmpb %r10b, (%rcx,%rax)
jne 0x3a07
movb (%rax), %cl
cmpb (%r8), %cl
jne 0x3a07
movb 0x1(%rax), %al
cmpb 0x1(%r8), %al
jne 0x3a07
cmpl %esi, -0x38(%rsp)
seta %cl
movq -0x30(%rsp), %rax
movl %eax, %edi
cmoval -0x58(%rsp), %edi
movl %esi, %r15d
subl %edi, %r15d
negl %r15d
movl %esi, %eax
subl %edi, %eax
cmovbl %r15d, %eax
movq -0x10(%rsp), %rdi
cmpq %rdi, -0x8(%rsp)
setl %dil
xorb %cl, %dil
movl -0x44(%rsp), %ecx
cmovnel -0x48(%rsp), %ecx
cmpl $0x7fff, %eax           # imm = 0x7FFF
ja 0x3a07
movl %ecx, -0x64(%rsp)
movq -0x28(%rsp), %rcx
leaq (%rcx,%rsi), %r15
xorl %ecx, %ecx
movb 0x3(%r8,%rcx), %r12b
cmpb -0x7(%r15,%rcx), %r12b
jne 0x3930
movb 0x4(%r8,%rcx), %r12b
cmpb -0x6(%r15,%rcx), %r12b
jne 0x393a
movb 0x5(%r8,%rcx), %r12b
cmpb -0x5(%r15,%rcx), %r12b
jne 0x3944
movb 0x6(%r8,%rcx), %r12b
cmpb -0x4(%r15,%rcx), %r12b
jne 0x394e
movb 0x7(%r8,%rcx), %r12b
cmpb -0x3(%r15,%rcx), %r12b
jne 0x3958
movb 0x8(%r8,%rcx), %r12b
cmpb -0x2(%r15,%rcx), %r12b
jne 0x3962
movb 0x9(%r8,%rcx), %r12b
cmpb -0x1(%r15,%rcx), %r12b
jne 0x396c
leaq 0x2(%rcx), %r13
leaq 0x8(%rcx), %r12
cmpq $0xff9, %r13            # imm = 0xFF9
ja 0x3926
movb (%r15,%rcx), %r13b
cmpb %r13b, 0xa(%r8,%rcx)
movq %r12, %rcx
je 0x38b3
leaq (%r8,%r12), %r15
addq $0x2, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x3, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x4, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x5, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x6, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x7, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x8, %r15
jmp 0x3974
leaq (%r8,%rcx), %r15
addq $0x9, %r15
subl -0x20(%rsp), %r15d
addl $0x1002, %r15d          # imm = 0x1002
movl -0x50(%rsp), %ecx
cmpl %ecx, %r15d
cmovael %ecx, %r15d
movq -0x18(%rsp), %rcx
subq %rsi, %rcx
movl $0xb, %r12d
movl %eax, %r13d
cmpl $0x2, %r13d
jb 0x39aa
shrl %r13d
incl %r12d
jmp 0x399c
movl %r15d, %r13d
cmpq %r13, %rcx
cmovael %r15d, %ecx
movl %ecx, %edi
imull -0x4c(%rsp), %edi
movl %edi, %r15d
subl %r12d, %r15d
cmpl -0x74(%rsp), %r15d
jg 0x39db
movl %edi, %r13d
subl -0x74(%rsp), %r13d
cmpl %r12d, %r13d
jne 0x3a07
cmpl -0x70(%rsp), %eax
jae 0x3a07
cmpl -0x68(%rsp), %ecx
jae 0x3a7a
leal -0x1(%rcx), %edi
movb (%r8,%rdi), %r10b
movl %ecx, %r14d
movl %eax, -0x70(%rsp)
movl %r15d, -0x74(%rsp)
movl -0x64(%rsp), %eax
movl %eax, -0x6c(%rsp)
movl %esi, %eax
movq %rax, -0x60(%rsp)
andl %r9d, %esi
movzwl (%rbx,%rsi,2), %esi
cmpl %esi, %edx
jae 0x3a1b
decl %r11d
jne 0x382f
movl -0x6c(%rsp), %ecx
cmpl $0x3, %ecx
je 0x3a6f
movq -0x40(%rsp), %rsi
movl %ecx, 0xc0(%rsi)
movl %r14d, 0xa8(%rsi)
movl -0x70(%rsp), %eax
movq %rax, 0xd0(%rsi)
movzwl -0x60(%rsp), %eax
movl %eax, 0xb8(%rsi)
movslq %ecx, %rcx
xorl %edx, %edx
cmpq %rax, 0x1a78(%rsi,%rcx,8)
setg %dl
shll $0x7, %edx
movl %edx, 0xc8(%rsi)
movl -0x74(%rsp), %eax
movl %eax, 0xe0(%rsi)
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
subl %r12d, %edi
movl %ecx, %r14d
movl %eax, -0x70(%rsp)
movl %edi, -0x74(%rsp)
movl -0x64(%rsp), %eax
movl %eax, -0x6c(%rsp)
movq %rsi, -0x60(%rsp)
jmp 0x3a1b