// File: sisong[P]ApkDiffPatch/zlib1.3.1/deflate.c
// Function: longest_match
local uInt longest_match(deflate_state *s, IPos cur_match) {
    unsigned chain_length = s->max_chain_length;/* max hash chain length */
    register Bytef *scan = s->window + s->strstart; /* current string */
    register Bytef *match;                      /* matched string */
    register int len;                           /* length of current match */
    int best_len = (int)s->prev_length;         /* best match length so far */
    int nice_match = s->nice_match;             /* stop if match long enough */
    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
        s->strstart - (IPos)MAX_DIST(s) : NIL;
    /* Stop when cur_match becomes <= limit. To simplify the code,
     * we prevent matches with the string of window index 0.
     */
    Posf *prev = s->prev;
    uInt wmask = s->w_mask;

#ifdef UNALIGNED_OK
    /* Compare two bytes at a time. Note: this is not always beneficial.
     * Try with and without -DUNALIGNED_OK to check.
     */
    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
    register ush scan_start = *(ushf*)scan;
    register ush scan_end   = *(ushf*)(scan + best_len - 1);
#else
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
    register Byte scan_end1  = scan[best_len - 1];
    register Byte scan_end   = scan[best_len];
#endif

    /* 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.
     */
    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

    /* Do not waste too much time if we already have a good match: */
    if (s->prev_length >= 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 = (int)s->lookahead;

    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
           "need lookahead");

    do {
        Assert(cur_match < s->strstart, "no future");
        match = s->window + cur_match;

        /* Skip to next match if the match length cannot increase
         * or if the match length is less than 2.  Note that the checks below
         * for insufficient lookahead only occur occasionally for performance
         * reasons.  Therefore uninitialized memory will be accessed, and
         * conditional jumps will be made that depend on those values.
         * However the length of the match is limited to the lookahead, so
         * the output of deflate is not affected by the uninitialized values.
         */
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
        /* This code assumes sizeof(unsigned short) == 2. Do not use
         * UNALIGNED_OK if your compiler uses a different size.
         */
        if (*(ushf*)(match + best_len - 1) != scan_end ||
            *(ushf*)match != scan_start) continue;

        /* 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. Compare 2 bytes at a time at
         * strstart + 3, + 5, up to strstart + 257. We check for insufficient
         * lookahead only every 4th comparison; the 128th check will be made
         * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
         * necessary to put more guard bytes at the end of the window, or
         * to check more often for insufficient lookahead.
         */
        Assert(scan[2] == match[2], "scan[2]?");
        scan++, match++;
        do {
        } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 scan < strend);
        /* The funny "do {}" generates better code on most compilers */

        /* Here, scan <= window + strstart + 257 */
        Assert(scan <= s->window + (unsigned)(s->window_size - 1),
               "wild scan");
        if (*scan == *match) scan++;

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

#else /* UNALIGNED_OK */

        if (match[best_len]     != scan_end  ||
            match[best_len - 1] != scan_end1 ||
            *match              != *scan     ||
            *++match            != scan[1])      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, "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;

#endif /* UNALIGNED_OK */

        if (len > best_len) {
            s->match_start = cur_match;
            best_len = len;
            if (len >= nice_match) break;
#ifdef UNALIGNED_OK
            scan_end = *(ushf*)(scan + best_len - 1);
#else
            scan_end1  = scan[best_len - 1];
            scan_end   = scan[best_len];
#endif
        }
    } while ((cur_match = prev[cur_match & wmask]) > limit
             && --chain_length != 0);

    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
    return s->lookahead;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rax
movl 0xbc(%rax), %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq -0x10(%rbp), %rcx
movl 0xac(%rcx), %ecx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl 0xb8(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movl 0xd0(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rax
movl 0xac(%rax), %eax
movq -0x10(%rbp), %rcx
movl 0x50(%rcx), %ecx
subl $0x106, %ecx            # imm = 0x106
cmpl %ecx, %eax
jbe 0x98404
movq -0x10(%rbp), %rax
movl 0xac(%rax), %eax
movq -0x10(%rbp), %rcx
movl 0x50(%rcx), %ecx
subl $0x106, %ecx            # imm = 0x106
subl %ecx, %eax
movl %eax, -0x58(%rbp)
jmp 0x9840b
xorl %eax, %eax
movl %eax, -0x58(%rbp)
jmp 0x9840b
movl -0x58(%rbp), %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq -0x10(%rbp), %rcx
movl 0xac(%rcx), %ecx
addq %rcx, %rax
addq $0x102, %rax            # imm = 0x102
movq %rax, -0x50(%rbp)
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x51(%rbp)
movq -0x20(%rbp), %rax
movslq -0x30(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x52(%rbp)
movq -0x10(%rbp), %rax
movl 0xb8(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0xcc(%rcx), %eax
jb 0x98486
movl -0x18(%rbp), %eax
shrl $0x2, %eax
movl %eax, -0x18(%rbp)
movl -0x34(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xb4(%rcx), %eax
jbe 0x984a2
movq -0x10(%rbp), %rax
movl 0xb4(%rax), %eax
movl %eax, -0x34(%rbp)
jmp 0x984a4
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movl -0x14(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movslq -0x30(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movzbl -0x52(%rbp), %ecx
cmpl %ecx, %eax
jne 0x98514
movq -0x28(%rbp), %rax
movl -0x30(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movzbl -0x51(%rbp), %ecx
cmpl %ecx, %eax
jne 0x98514
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
movq -0x20(%rbp), %rcx
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jne 0x98514
movq -0x28(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x28(%rbp)
movzbl 0x1(%rax), %eax
movq -0x20(%rbp), %rcx
movzbl 0x1(%rcx), %ecx
cmpl %ecx, %eax
je 0x98519
jmp 0x98745
movq -0x20(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x98533
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x20(%rbp)
movzbl 0x1(%rax), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x28(%rbp)
movzbl 0x1(%rax), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jne 0x986cd
movq -0x20(%rbp), %rax
cmpq -0x50(%rbp), %rax
setb %al
movb %al, -0x59(%rbp)
movb -0x59(%rbp), %al
testb $0x1, %al
jne 0x98531
movq -0x50(%rbp), %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
movl %eax, %ecx
movl $0x102, %eax            # imm = 0x102
subl %ecx, %eax
movl %eax, -0x2c(%rbp)
movq -0x50(%rbp), %rax
addq $-0x102, %rax           # imm = 0xFEFE
movq %rax, -0x20(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jle 0x98743
movl -0x14(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0xb0(%rax)
movl -0x2c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jl 0x98722
jmp 0x9877f
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x51(%rbp)
movq -0x20(%rbp), %rax
movslq -0x30(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x52(%rbp)
jmp 0x98745
movq -0x40(%rbp), %rax
movl -0x14(%rbp), %ecx
andl -0x44(%rbp), %ecx
movl %ecx, %ecx
movzwl (%rax,%rcx,2), %ecx
movl %ecx, -0x14(%rbp)
xorl %eax, %eax
cmpl -0x38(%rbp), %ecx
movb %al, -0x5a(%rbp)
jbe 0x98774
movl -0x18(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x18(%rbp)
cmpl $0x0, %eax
setne %al
movb %al, -0x5a(%rbp)
movb -0x5a(%rbp), %al
testb $0x1, %al
jne 0x984a4
movl -0x30(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xb4(%rcx), %eax
ja 0x98796
movl -0x30(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x987a3
movq -0x10(%rbp), %rax
movl 0xb4(%rax), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
popq %rbp
retq
nopl (%rax,%rax)