// File: /workspace/github_c_makefile_star2_O3/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
movslq %edx, %rax
leal (%rax,%rax), %ecx
movl %ecx, -0x4c(%rsp)
movslq %ecx, %rcx
movq 0x1a78(%rdi,%rcx,8), %r8
leal 0x1(%rax,%rax), %ecx
movl %ecx, -0x50(%rsp)
movslq %ecx, %rcx
movq 0x1a78(%rdi,%rcx,8), %r9
cmpq %r9, %r8
movq %r9, %rcx
cmovlq %r8, %rcx
movq %r9, %rdx
cmovgq %r8, %rdx
movq %rdx, -0x38(%rsp)
movq %rcx, -0x40(%rsp)
testq %rcx, %rcx
js 0x3866
leaq (%r9,%r8), %rcx
movq %rcx, %rdx
shrq $0x3f, %rdx
addq %rcx, %rdx
shrq %rdx
movq %rdx, -0x48(%rsp)
jmp 0x386f
movq $0x0, -0x48(%rsp)
movq 0x70(%rdi,%rax,8), %rbx
movl 0x44(%rdi), %ebp
movl $0x8000, %ecx           # imm = 0x8000
movq -0x38(%rsp), %rdx
addl %ecx, %edx
cmpl %esi, %edx
jae 0x388f
andl %ebp, %esi
movzwl (%rbx,%rsi,2), %esi
jmp 0x3883
testl %esi, %esi
je 0x3baf
movq %r9, -0x10(%rsp)
movq %r8, -0x8(%rsp)
movl 0xb4(%rdi), %edx
movl 0xa8(%rdi), %r14d
movq 0x48(%rdi), %r8
leal -0x1(%r14), %r9d
leaq (%r8,%rdx), %r13
movq -0x40(%rsp), %r11
movzwl %r11w, %r12d
movl 0xf8(%rdi), %r10d
movl %r10d, -0x54(%rsp)
movl 0xec(%rdi), %r10d
movl 0xd0(%rdi), %r15d
movl %r15d, -0x74(%rsp)
movl 0xe0(%rdi), %r15d
movl %r15d, -0x70(%rsp)
movl 0x100(%rdi), %ecx
movq 0x60(%rdi,%rax,8), %r15
movq %r15, -0x18(%rsp)
leaq 0x1002(%r8,%rdx), %rdx
movq %rdx, -0x20(%rsp)
movb (%r9,%r13), %dl
movl $0x8000, %r8d           # imm = 0x8000
xorl %r8d, %r12d
movl %r10d, %r15d
shrl $0x2, %r15d
cmpl 0xfc(%rdi), %r14d
cmovbl %r10d, %r15d
movl 0xbc(%rdi), %r8d
cmpl %r8d, %ecx
movl %r8d, -0x58(%rsp)
cmovael %r8d, %ecx
movl %ecx, -0x5c(%rsp)
xorl %ecx, %ecx
cmpq $0x8001, %r11           # imm = 0x8001
cmovll %ecx, %r12d
movq %rdi, -0x30(%rsp)
movq 0x50(%rdi,%rax,8), %rax
leaq 0xa(%rax), %rcx
movq %rcx, -0x28(%rsp)
movl $0x3, -0x6c(%rsp)
movq $0x0, -0x68(%rsp)
movl %esi, %esi
leaq (%rax,%rsi), %rcx
leal -0x1(%r14), %r8d
cmpb %dl, (%r8,%rcx)
jne 0x3b47
movb (%rcx), %r8b
cmpb (%r13), %r8b
jne 0x3b47
movb 0x1(%rcx), %cl
cmpb 0x1(%r13), %cl
jne 0x3b47
cmpl %esi, -0x48(%rsp)
seta %cl
movq -0x38(%rsp), %rdi
movl %edi, %r8d
cmoval -0x40(%rsp), %r8d
movl %esi, %r9d
subl %r8d, %r9d
negl %r9d
movl %esi, %r10d
subl %r8d, %r10d
cmovbl %r9d, %r10d
movq -0x10(%rsp), %rdi
cmpq %rdi, -0x8(%rsp)
setl %r8b
xorb %cl, %r8b
movl -0x4c(%rsp), %edi
cmovnel -0x50(%rsp), %edi
cmpl $0x7fff, %r10d          # imm = 0x7FFF
ja 0x3b47
movq -0x28(%rsp), %rcx
leaq (%rcx,%rsi), %r11
xorl %r8d, %r8d
movb 0x3(%r13,%r8), %r9b
cmpb -0x7(%r11,%r8), %r9b
jne 0x3a78
movb 0x4(%r13,%r8), %r9b
cmpb -0x6(%r11,%r8), %r9b
jne 0x3a82
movb 0x5(%r13,%r8), %r9b
cmpb -0x5(%r11,%r8), %r9b
jne 0x3a8c
movb 0x6(%r13,%r8), %r9b
cmpb -0x4(%r11,%r8), %r9b
jne 0x3a96
movb 0x7(%r13,%r8), %r9b
cmpb -0x3(%r11,%r8), %r9b
jne 0x3aa0
movb 0x8(%r13,%r8), %r9b
cmpb -0x2(%r11,%r8), %r9b
jne 0x3aaa
movb 0x9(%r13,%r8), %r9b
cmpb -0x1(%r11,%r8), %r9b
jne 0x3ab4
leaq 0x2(%r8), %rcx
leaq 0x8(%r8), %r9
cmpq $0xff9, %rcx            # imm = 0xFF9
ja 0x3a6e
movb (%r11,%r8), %cl
cmpb %cl, 0xa(%r13,%r8)
movq %r9, %r8
je 0x39fb
leaq (%r9,%r13), %r11
addq $0x2, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x3, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x4, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x5, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x6, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x7, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x8, %r11
jmp 0x3abc
leaq (%r8,%r13), %r11
addq $0x9, %r11
subl -0x20(%rsp), %r11d
addl $0x1002, %r11d          # imm = 0x1002
movl -0x58(%rsp), %ecx
cmpl %ecx, %r11d
cmovael %ecx, %r11d
movq -0x18(%rsp), %r8
subq %rsi, %r8
cmpq %r11, %r8
cmovael %r11d, %r8d
bsrl %r10d, %ecx
xorl $0x1f, %ecx
addl $-0x1f, %ecx
cmpl $0x2, %r10d
movl $0x0, %r9d
cmovbl %r9d, %ecx
movl %r8d, %r9d
imull -0x54(%rsp), %r9d
leal (%r9,%rcx), %r11d
addl $-0xb, %r11d
cmpl -0x70(%rsp), %r11d
jg 0x3b1b
jne 0x3b47
cmpl -0x74(%rsp), %r10d
jae 0x3b47
cmpl -0x5c(%rsp), %r8d
jae 0x3bba
leal -0x1(%r8), %ecx
movb (%r13,%rcx), %dl
movl %r8d, %r14d
movl %r10d, -0x74(%rsp)
movl %r11d, -0x70(%rsp)
movl %edi, -0x6c(%rsp)
movl %esi, %ecx
movq %rcx, -0x68(%rsp)
andl %ebp, %esi
movzwl (%rbx,%rsi,2), %esi
cmpl %esi, %r12d
jae 0x3b5b
decl %r15d
jne 0x3972
movl -0x6c(%rsp), %ecx
cmpl $0x3, %ecx
movq -0x30(%rsp), %rsi
je 0x3baf
movl %ecx, 0xc0(%rsi)
movl %r14d, 0xa8(%rsi)
movl -0x74(%rsp), %eax
movq %rax, 0xd0(%rsi)
movzwl -0x68(%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 -0x70(%rsp), %eax
movl %eax, 0xe0(%rsi)
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %r8d, %r14d
movl %r10d, -0x74(%rsp)
movl %r11d, -0x70(%rsp)
movl %edi, -0x6c(%rsp)
movq %rsi, -0x68(%rsp)
jmp 0x3b5b