// File: sisong[P]ApkDiffPatch/lzma/C/LzFindOpt.c
// Function: GetMatchesSpecN_2
Z7_NO_INLINE
UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
    UInt32 *posRes)
{
  do // while (hash != size)
  {
    UInt32 delta;
    
  #ifndef cbs
    UInt32 cbs;
  #endif

    if (hash == size)
      break;

    delta = *hash++;

    if (delta == 0)
      return NULL;

    lenLimit++;

  #ifndef cbs
    cbs = _cyclicBufferSize;
    if ((UInt32)pos < cbs)
    {
      if (delta > (UInt32)pos)
        return NULL;
      cbs = (UInt32)pos;
    }
  #endif

    if (delta >= cbs)
    {
      CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
      *d++ = 0;
      ptr1[0] = kEmptyHashValue;
      ptr1[1] = kEmptyHashValue;
    }
else
{
  UInt32 *_distances = ++d;

  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);

  UInt32 cutValue = _cutValue;
  const Byte *len0 = cur, *len1 = cur;
  const Byte *maxLen = cur + _maxLen;

  // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else
  for (LOG_ITER(g_NumIters_Tree++);;)
  {
    LOG_ITER(g_NumIters_Loop++);
    {
      // SPEC code
      CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta
          + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)
          ) << 1);

      const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
      const Byte *len = (len0 < len1 ? len0 : len1);

    #ifdef USE_SON_PREFETCH
      const UInt32 pair0 = *pair;
    #endif

      if (len[diff] == len[0])
      {
        if (++len != lenLimit && len[diff] == len[0])
          while (++len != lenLimit)
          {
            LOG_ITER(g_NumIters_Bytes++);
            if (len[diff] != len[0])
              break;
          }
        if (maxLen < len)
        {
          maxLen = len;
          *d++ = (UInt32)(len - cur);
          *d++ = delta - 1;
          
          if (len == lenLimit)
          {
            const UInt32 pair1 = pair[1];
            *ptr1 =
              #ifdef USE_SON_PREFETCH
                pair0;
              #else
                pair[0];
              #endif
            *ptr0 = pair1;

            _distances[-1] = (UInt32)(d - _distances);

            #ifdef USE_LONG_MATCH_OPT

                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
                  break;

            {
              for (;;)
              {
                *d++ = 2;
                *d++ = (UInt32)(lenLimit - cur);
                *d++ = delta - 1;
                cur++;
                lenLimit++;
                // SPEC
                _cyclicBufferPos++;
                {
                  // SPEC code
                  CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1);
                  const CLzRef *src = dest + ((diff
                      + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1);
                  // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
                  #if 0
                  *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);
                  #else
                  const UInt32 p0 = src[0];
                  const UInt32 p1 = src[1];
                  dest[0] = p0;
                  dest[1] = p1;
                  #endif
                }
                pos++;
                hash++;
                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
                  break;
              } // for() end for long matches
            }
            #endif

            break; // break from TREE iterations
          }
        }
      }
      {
        const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);
        if (len[diff] < len[0])
        {
          delta = pair[1];
          *ptr1 = curMatch;
          ptr1 = pair + 1;
          len1 = len;
          if (delta >= curMatch)
            return NULL;
        }
        else
        {
          delta = *pair;
          *ptr0 = curMatch;
          ptr0 = pair;
          len0 = len;
          if (delta >= curMatch)
            return NULL;
        }
        delta = (UInt32)pos - delta;
 
        if (--cutValue == 0 || delta >= cbs)
        {
          *ptr0 = *ptr1 = kEmptyHashValue;
          _distances[-1] = (UInt32)(d - _distances);
          break;
        }
      }
    }
  } // for (tree iterations)
}
    pos++;
    _cyclicBufferPos++;
    cur++;
  }
  while (d < limit);
  *posRes = (UInt32)pos;
  return d;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x78, %rsp
movq 0x40(%rbp), %rax
movl 0x38(%rbp), %eax
movq 0x30(%rbp), %rax
movq 0x28(%rbp), %rax
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movl %r8d, -0x2c(%rbp)
movq %r9, -0x38(%rbp)
movq 0x18(%rbp), %rax
cmpq 0x28(%rbp), %rax
jne 0x77a0a
jmp 0x78028
movq 0x18(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x18(%rbp)
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jne 0x77a31
movq $0x0, -0x8(%rbp)
jmp 0x7803c
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
movl 0x38(%rbp), %eax
movl %eax, -0x40(%rbp)
movq -0x18(%rbp), %rax
cmpl -0x40(%rbp), %eax
jae 0x77a6b
movl -0x3c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl %ecx, %eax
jbe 0x77a64
movq $0x0, -0x8(%rbp)
jmp 0x7803c
movq -0x18(%rbp), %rax
movl %eax, -0x40(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x40(%rbp), %eax
jb 0x77ab8
movq -0x28(%rbp), %rax
movq 0x30(%rbp), %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x38(%rbp)
movl $0x0, (%rax)
movq -0x48(%rbp), %rax
movl $0x0, (%rax)
movq -0x48(%rbp), %rax
movl $0x0, 0x4(%rax)
jmp 0x77ff6
movq -0x38(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x38(%rbp)
movq %rax, -0x50(%rbp)
movq -0x28(%rbp), %rax
movq 0x30(%rbp), %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
addq $0x4, %rax
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rax
movq 0x30(%rbp), %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x64(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x20(%rbp), %rax
addq 0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq 0x30(%rbp), %rax
movl -0x3c(%rbp), %ecx
subq %rcx, %rax
movq %rax, -0xc8(%rbp)
movq 0x30(%rbp), %rax
movl -0x3c(%rbp), %ecx
cmpq %rcx, %rax
jae 0x77b4d
movl -0x40(%rbp), %eax
movl %eax, -0xd4(%rbp)
jmp 0x77b57
xorl %eax, %eax
movl %eax, -0xd4(%rbp)
jmp 0x77b57
movq -0xd0(%rbp), %rax
movq -0xc8(%rbp), %rcx
movl -0xd4(%rbp), %edx
movl %edx, %edx
addq %rdx, %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x88(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, %ecx
xorl %eax, %eax
subq %rcx, %rax
movq %rax, -0x90(%rbp)
movq -0x70(%rbp), %rax
cmpq -0x78(%rbp), %rax
jae 0x77ba9
movq -0x70(%rbp), %rax
movq %rax, -0xe0(%rbp)
jmp 0x77bb4
movq -0x78(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x88(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x9c(%rbp)
movq -0x98(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x98(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x77edf
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
cmpq -0x10(%rbp), %rax
je 0x77c6d
movq -0x98(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x98(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x77c6d
jmp 0x77c2f
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
cmpq -0x10(%rbp), %rax
je 0x77c6b
movq -0x98(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x98(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
je 0x77c69
jmp 0x77c6b
jmp 0x77c2f
jmp 0x77c6d
movq -0x80(%rbp), %rax
cmpq -0x98(%rbp), %rax
jae 0x77edd
movq -0x98(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x98(%rbp), %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
movl %eax, %ecx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, (%rax)
movl -0x3c(%rbp), %ecx
subl $0x1, %ecx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, (%rax)
movq -0x98(%rbp), %rax
cmpq -0x10(%rbp), %rax
jne 0x77edb
movq -0x88(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xa0(%rbp)
movl -0x9c(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, (%rax)
movl -0xa0(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
movq -0x50(%rbp), %rcx
subq %rcx, %rax
sarq $0x2, %rax
movl %eax, %ecx
movq -0x50(%rbp), %rax
movl %ecx, -0x4(%rax)
movq 0x18(%rbp), %rax
cmpq 0x28(%rbp), %rax
je 0x77d4b
movq 0x18(%rbp), %rax
movl (%rax), %eax
cmpl -0x3c(%rbp), %eax
jne 0x77d4b
movq -0x10(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x10(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x77d4b
movq -0x38(%rbp), %rax
cmpq 0x20(%rbp), %rax
jb 0x77d50
jmp 0x77ff4
jmp 0x77d52
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x38(%rbp)
movl $0x2, (%rax)
movq -0x10(%rbp), %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
movl %eax, %ecx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, (%rax)
movl -0x3c(%rbp), %ecx
subl $0x1, %ecx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
movq 0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, 0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x30(%rbp), %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq 0x30(%rbp), %rax
movl -0x3c(%rbp), %ecx
cmpq %rcx, %rax
jae 0x77e0c
movl -0x40(%rbp), %eax
movl %eax, -0xf4(%rbp)
jmp 0x77e16
xorl %eax, %eax
movl %eax, -0xf4(%rbp)
jmp 0x77e16
movq -0xf0(%rbp), %rax
movq -0xe8(%rbp), %rcx
movl -0xf4(%rbp), %edx
movl %edx, %edx
addq %rdx, %rcx
shlq %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xb4(%rbp)
movq -0xb0(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xb8(%rbp)
movl -0xb4(%rbp), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, (%rax)
movl -0xb8(%rbp), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x18(%rbp)
movq 0x18(%rbp), %rax
addq $0x4, %rax
movq %rax, 0x18(%rbp)
movq 0x18(%rbp), %rax
cmpq 0x28(%rbp), %rax
je 0x77ecf
movq 0x18(%rbp), %rax
movl (%rax), %eax
cmpl -0x3c(%rbp), %eax
jne 0x77ecf
movq -0x10(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x10(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x77ecf
movq -0x38(%rbp), %rax
cmpq 0x20(%rbp), %rax
jb 0x77ed1
jmp 0x77ed6
jmp 0x77d52
jmp 0x77ff4
jmp 0x77edd
jmp 0x77edf
movq -0x18(%rbp), %rax
subl -0x3c(%rbp), %eax
movl %eax, -0xbc(%rbp)
movq -0x98(%rbp), %rax
movq -0x90(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movq -0x98(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jge 0x77f59
movq -0x88(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0xbc(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, (%rax)
movq -0x88(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x60(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x78(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0xbc(%rbp), %eax
jb 0x77f57
movq $0x0, -0x8(%rbp)
jmp 0x7803c
jmp 0x77fa1
movq -0x88(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0xbc(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x88(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x70(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0xbc(%rbp), %eax
jb 0x77f9f
movq $0x0, -0x8(%rbp)
jmp 0x7803c
jmp 0x77fa1
movq -0x18(%rbp), %rax
subl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x64(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x64(%rbp)
cmpl $0x0, %eax
je 0x77fc1
movl -0x3c(%rbp), %eax
cmpl -0x40(%rbp), %eax
jb 0x77fef
movq -0x60(%rbp), %rax
movl $0x0, (%rax)
movq -0x58(%rbp), %rax
movl $0x0, (%rax)
movq -0x38(%rbp), %rax
movq -0x50(%rbp), %rcx
subq %rcx, %rax
sarq $0x2, %rax
movl %eax, %ecx
movq -0x50(%rbp), %rax
movl %ecx, -0x4(%rax)
jmp 0x77ff4
jmp 0x77b1a
jmp 0x77ff6
movq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x18(%rbp)
movq 0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, 0x30(%rbp)
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
movq -0x38(%rbp), %rax
cmpq 0x20(%rbp), %rax
jb 0x779fb
movq -0x18(%rbp), %rax
movl %eax, %ecx
movq 0x40(%rbp), %rax
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x78, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)