// File: /workspace/github_c_makefile_star2_O3/DavidSM64[P]DKR-Decompressor/DKRGzip.c
// Function: longest_match(unsigned int)
int longest_match(IPos cur_match) {
    unsigned chain_length = max_chain_length;   /* max hash chain length */
    u8 *scan = window + strstart;     /* current string */
    u8 *match;                        /* matched string */
    int len;                           /* length of current match */
    int best_len = prev_length;                 /* best match length so far */
    IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
    /* Stop when cur_match becomes <= limit. To simplify the code,
     * we prevent matches with the string of window index 0.
     */

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

    /* Do not waste too mu8 time if we already have a good match: */
    if (prev_length >= good_match) {
        chain_length >>= 2;
    }
    //Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");

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

        /* Skip to next match if the match length cannot increase
         * or if the match length is less than 2:
         */
#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 (*(u16*)(match+best_len-1) != scan_end ||
            *(u16*)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.
         */
        scan++, match++;
        do {
        } while (*(u16*)(scan+=2) == *(u16*)(match+=2) &&
                 *(u16*)(scan+=2) == *(u16*)(match+=2) &&
                 *(u16*)(scan+=2) == *(u16*)(match+=2) &&
                 *(u16*)(scan+=2) == *(u16*)(match+=2) &&
                 scan < strend);
        /* The funny "do {}" generates better code on most compilers */

        /* Here, scan <= window+strstart+257 */
        //Assert(scan <= window+(unsigned)(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++;

        /* 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);

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

#endif /* UNALIGNED_OK */

        if (len > best_len) {
            match_start = cur_match;
            best_len = len;
            if (len >= nice_match) break;
#ifdef UNALIGNED_OK
            scan_end = *(u16*)(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);

    return best_len;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movl 0x5f21(%rip), %r10d     # 0xabb8
movl 0x5f0e(%rip), %r8d      # 0xabac
leaq 0x1008e9b(%rip), %rcx   # 0x100db40
leaq (%rcx,%r8), %rdx
movslq 0x5ef8(%rip), %rax      # 0xaba8
xorl %r9d, %r9d
leaq (%r8,%rcx), %rsi
addq $0x102, %rsi            # imm = 0x102
subl $0x7efa, %r8d           # imm = 0x7EFA
cmovbl %r9d, %r8d
movb -0x1(%rax,%rdx), %bl
movb (%rax,%rdx), %r14b
movl %r10d, %r9d
shrl $0x2, %r9d
cmpl 0x5ee6(%rip), %eax      # 0xabc4
cmovbl %r10d, %r9d
movl 0x5ee7(%rip), %r10d     # 0xabd0
movl %r10d, -0x2c(%rbp)
leaq 0x1018e4c(%rip), %r11   # 0x101db40
movl %edi, %r15d
leaq (%rcx,%r15), %r12
movslq %eax, %r13
cmpb %r14b, (%r13,%r12)
jne 0x4e27
cmpb %bl, -0x1(%r12,%r13)
jne 0x4e27
movb (%r12), %r13b
cmpb (%rdx), %r13b
jne 0x4e27
movb 0x1(%r12), %r12b
cmpb 0x1(%rdx), %r12b
jne 0x4e27
leaq (%r15,%rcx), %r12
addq $0xa, %r12
xorl %r15d, %r15d
movb 0x3(%rdx,%r15), %r13b
cmpb -0x7(%r12,%r15), %r13b
jne 0x4db8
movb 0x4(%rdx,%r15), %r13b
cmpb -0x6(%r12,%r15), %r13b
jne 0x4dc1
movb 0x5(%rdx,%r15), %r13b
cmpb -0x5(%r12,%r15), %r13b
jne 0x4dca
movb 0x6(%rdx,%r15), %r13b
cmpb -0x4(%r12,%r15), %r13b
jne 0x4dd3
movb 0x7(%rdx,%r15), %r13b
cmpb -0x3(%r12,%r15), %r13b
jne 0x4ddc
movb 0x8(%rdx,%r15), %r13b
cmpb -0x2(%r12,%r15), %r13b
jne 0x4de5
movb 0x9(%rdx,%r15), %r13b
cmpb -0x1(%r12,%r15), %r13b
jne 0x4dee
leaq 0x2(%r15), %r10
leaq 0x8(%r15), %r13
cmpq $0xf9, %r10
ja 0x4dae
movb (%r12,%r15), %r10b
cmpb %r10b, 0xa(%rdx,%r15)
movq %r13, %r15
je 0x4d3b
leaq (%rdx,%r13), %r15
addq $0x2, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x3, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x4, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x5, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x6, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x7, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x8, %r15
jmp 0x4df5
addq %rdx, %r15
addq $0x9, %r15
subq %rsi, %r15
leal 0x102(%r15), %r12d
cmpl %eax, %r12d
jle 0x4e27
movl %edi, 0x5da6(%rip)      # 0xabb0
cmpl -0x2c(%rbp), %r12d
jge 0x4e4b
addl $0x101, %r15d           # imm = 0x101
movslq %r15d, %rax
movb (%rdx,%rax), %bl
movslq %r12d, %rax
movb (%rdx,%rax), %r14b
movl %r12d, %eax
andl $0x7fff, %edi           # imm = 0x7FFF
movzwl (%r11,%rdi,2), %edi
cmpl %edi, %r8d
jae 0x4e40
decl %r9d
jne 0x4cf4
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %r12d, %eax
jmp 0x4e40