// File: /workspace/github_c_makefile_star2_O0/salextpuru[P]speccy-toochain/src/mhmt/mhmt-lz.c
// Function: make_lz_codes
void make_lz_codes(ULONG position, ULONG actual_len, UBYTE * hash, struct lzcode * codes)
{
    ULONG codepos;
    ULONG codelen,i;
    ULONG was_match;
    UBYTE curr_byte,next_byte;
    struct tb_chain * curr_tb;
    UWORD index;
    ULONG max_lookback,max_length,max_tbdisp;
    // copy-byte code is always present
    codes[0].length = 1;
    codes[0].disp   = 0;
    // start more filling of codes[] from that position
    codepos = 1;

    if( wrk.packtype==PK_HST ) { // for hrust only,
        // add 12,14,16,...,40,42 bytes copies, if possible
        for(codelen=12; codelen<=42; codelen+=2) {
            if( position <= (actual_len-codelen) ) {
                codes[codepos].length = codelen;
                codes[codepos].disp   = 0;
                codepos++;

            } else
                break;
        }
    }

    // check for one-byter (-1..-8)
    //
    curr_byte=wrk.indata[position];
    //
    i = (position>8) ? position-8 : 0;

    do {
        if( wrk.indata[i] == curr_byte ) {
            codes[codepos].length = 1;
            codes[codepos].disp   = -(LONG)(position-i);
            codepos++;
            break;
        }
    } while( (++i)<position );

    // for hrust, check 3-byte insertion code (-1..-79)
    if( (wrk.packtype==PK_HST) && (position < (actual_len-2)) ) {
        i = (position>79) ? position-79 : 0;

        do {
            if( (wrk.indata[i]==curr_byte) && (wrk.indata[i+2]==wrk.indata[position+2]) ) {
                codes[codepos].length = (-3);
                codes[codepos].disp   = -(LONG)(position-i);
                codepos++;
                break;
            }
        } while( (++i)<position );
    }

    switch( wrk.packtype ) { // set maximum lookback and length
    case PK_MLZ:
        max_lookback = (wrk.maxwin<4352) ? wrk.maxwin : 4352;
        max_length = 255;
        max_tbdisp = 256;
        break;

    case PK_HRM:
        max_lookback = (wrk.maxwin<4096) ? wrk.maxwin : 4096;
        max_length = 255;
        max_tbdisp = 256;
        break;

    case PK_HST:
        max_lookback = (wrk.maxwin<65536) ? wrk.maxwin : 65536;
        max_length = 3839;
        max_tbdisp = 768;
        break;

    default:
        printf("mhmt-lz.c:make_lz_codes() - wrong packer type!\n");
        exit(1);
    }

    // check for two-byter (-1..-max_tbdisp)
    //
    curr_tb = NULL;

    //
    if( position<(actual_len-1) ) { // don't try two-byter if we are at the byte before last one
        next_byte = wrk.indata[position+1];
        index=(curr_byte<<8) + next_byte;
        curr_tb = tb_entry[index];

        // there are two-byters!
        if( curr_tb ) {
            if( ((position-curr_tb->pos)<=max_tbdisp) && ((position-curr_tb->pos)<=max_lookback) ) {
                codes[codepos].length = 2;
                codes[codepos].disp   = -(LONG)(position - curr_tb->pos);
                codepos++;
            }
        }
    }

    // at last, check for lengths=3..max_length up to max_lookback
    if(  curr_tb  &&  ( (position-curr_tb->pos)<=max_lookback )  &&  ( position<(actual_len-2) )  ) { // if we can proceed at all
        was_match = 1; // there was match at codelen-1

        for( codelen=3; ( codelen<=max_length )&&( position<(actual_len-codelen+1) ); /*nothing*/ ) {
            if( was_match ) { // for codelen-1
                // codelen-1 bytes are matched, compare one more byte
                if( wrk.indata[position+codelen-1] == wrk.indata[curr_tb->pos+codelen-1] ) {
                    // add code to the table
                    codes[codepos].length = codelen;
                    codes[codepos].disp   = -(LONG)(position - curr_tb->pos);
                    codepos++;
                    codelen++; // next time do comparision of greater size

                } else { // last bytes do not match
MATCH_FAIL: // entrance for failed matches here: used 3-fold so we set "goto" here
                    // go for older twobyter
                    curr_tb = curr_tb->next;

                    // no more twobyters or they are too far - stop search at all
                    if( !curr_tb ) break;

                    if( (position - curr_tb->pos)>max_lookback ) break;

                    // mark there was no matches
                    was_match = 0;
                }

            } else { // there were no matches for previous codelen
                // next twobyter is already taken, but no comparision is done for codelen bytes
                // first we check if we need to do such comparision at all by seeing to the hashes of the ends of strings
                if( hash[position+codelen-1] == hash[curr_tb->pos+codelen-1] ) {
                    // hashes match, so try matching complete string
                    if( !memcmp( &wrk.indata[position], &wrk.indata[curr_tb->pos], codelen ) ) {
                        was_match = 1;
                        codes[codepos].length = codelen;
                        codes[codepos].disp   = -(LONG)(position - curr_tb->pos);
                        codepos++;
                        codelen++;

                    } else
                        // no match of whole string
                        goto MATCH_FAIL;

                } else
                    // no match of hashes
                    goto MATCH_FAIL;
            }
        }
    }

    // here we assume to have found all possible matches. check for codes[] table overflow:
    // there could be matches for length 1..3839, and there is copy-1-byte, 16 copymanybyters, 1 insertion match, total 3857 entries for hrust, 256 for megalz & hrum
    if(   codepos > ( (wrk.packtype==PK_HST) ? 3857 : 256 )   ) { // this should not happen!
        printf("mhmt-lz.c:make_lz_codes_hrust() encountered too many entries in codes[] table. Fatal error.\n");
        exit(1);
    }

    // mark end-of-records in codes[]
    codes[codepos].length = 0;
    codes[codepos].disp   = 0;
}

// Assembly:
subq $0x68, %rsp
movl %edi, 0x64(%rsp)
movl %esi, 0x60(%rsp)
movq %rdx, 0x58(%rsp)
movq %rcx, 0x50(%rsp)
movq 0x50(%rsp), %rax
movl $0x1, (%rax)
movq 0x50(%rsp), %rax
movl $0x0, 0x4(%rax)
movl $0x1, 0x4c(%rsp)
leaq 0xa7d4(%rip), %rax      # 0xe3a0
cmpl $0x3, (%rax)
jne 0x3c31
movl $0xc, 0x48(%rsp)
cmpl $0x2a, 0x48(%rsp)
ja 0x3c2f
movl 0x64(%rsp), %eax
movl 0x60(%rsp), %ecx
subl 0x48(%rsp), %ecx
cmpl %ecx, %eax
ja 0x3c1e
movl 0x48(%rsp), %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, (%rax,%rcx,8)
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0x0, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x3c20
jmp 0x3c2f
jmp 0x3c22
movl 0x48(%rsp), %eax
addl $0x2, %eax
movl %eax, 0x48(%rsp)
jmp 0x3bd9
jmp 0x3c31
leaq 0xa768(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x64(%rsp), %ecx
movb (%rax,%rcx), %al
movb %al, 0x3f(%rsp)
cmpl $0x8, 0x64(%rsp)
jbe 0x3c5b
movl 0x64(%rsp), %eax
subl $0x8, %eax
movl %eax, 0x1c(%rsp)
jmp 0x3c63
xorl %eax, %eax
movl %eax, 0x1c(%rsp)
jmp 0x3c63
movl 0x1c(%rsp), %eax
movl %eax, 0x44(%rsp)
leaq 0xa72e(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x44(%rsp), %ecx
movzbl (%rax,%rcx), %eax
movzbl 0x3f(%rsp), %ecx
cmpl %ecx, %eax
jne 0x3cbd
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0x1, (%rax,%rcx,8)
movl 0x64(%rsp), %eax
subl 0x44(%rsp), %eax
xorl %edx, %edx
subl %eax, %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x3cd0
jmp 0x3cbf
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
cmpl 0x64(%rsp), %eax
jb 0x3c6b
leaq 0xa6c9(%rip), %rax      # 0xe3a0
cmpl $0x3, (%rax)
jne 0x3db6
movl 0x64(%rsp), %eax
movl 0x60(%rsp), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jae 0x3db6
cmpl $0x4f, 0x64(%rsp)
jbe 0x3d07
movl 0x64(%rsp), %eax
subl $0x4f, %eax
movl %eax, 0x18(%rsp)
jmp 0x3d0f
xorl %eax, %eax
movl %eax, 0x18(%rsp)
jmp 0x3d0f
movl 0x18(%rsp), %eax
movl %eax, 0x44(%rsp)
leaq 0xa682(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x44(%rsp), %ecx
movzbl (%rax,%rcx), %eax
movzbl 0x3f(%rsp), %ecx
cmpl %ecx, %eax
jne 0x3d9d
leaq 0xa666(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x44(%rsp), %ecx
addl $0x2, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
leaq 0xa64e(%rip), %rcx      # 0xe3a0
movq 0x40(%rcx), %rcx
movl 0x64(%rsp), %edx
addl $0x2, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x3d9d
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0xfffffffd, (%rax,%rcx,8) # imm = 0xFFFFFFFD
movl 0x64(%rsp), %eax
subl 0x44(%rsp), %eax
xorl %edx, %edx
subl %eax, %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x3db4
jmp 0x3d9f
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
cmpl 0x64(%rsp), %eax
jb 0x3d17
jmp 0x3db6
leaq 0xa5e3(%rip), %rax      # 0xe3a0
movl (%rax), %eax
movl %eax, 0x14(%rsp)
subl $0x1, %eax
je 0x3de7
jmp 0x3dca
movl 0x14(%rsp), %eax
subl $0x2, %eax
je 0x3e2f
jmp 0x3dd5
movl 0x14(%rsp), %eax
subl $0x3, %eax
je 0x3e74
jmp 0x3eb9
leaq 0xa5b2(%rip), %rax      # 0xe3a0
cmpl $0x1100, 0x1c(%rax)     # imm = 0x1100
jae 0x3e07
leaq 0xa5a2(%rip), %rax      # 0xe3a0
movl 0x1c(%rax), %eax
movl %eax, 0x10(%rsp)
jmp 0x3e12
movl $0x1100, %eax           # imm = 0x1100
movl %eax, 0x10(%rsp)
jmp 0x3e12
movl 0x10(%rsp), %eax
movl %eax, 0x28(%rsp)
movl $0xff, 0x24(%rsp)
movl $0x100, 0x20(%rsp)      # imm = 0x100
jmp 0x3ed1
leaq 0xa56a(%rip), %rax      # 0xe3a0
cmpl $0x1000, 0x1c(%rax)     # imm = 0x1000
jae 0x3e4f
leaq 0xa55a(%rip), %rax      # 0xe3a0
movl 0x1c(%rax), %eax
movl %eax, 0xc(%rsp)
jmp 0x3e5a
movl $0x1000, %eax           # imm = 0x1000
movl %eax, 0xc(%rsp)
jmp 0x3e5a
movl 0xc(%rsp), %eax
movl %eax, 0x28(%rsp)
movl $0xff, 0x24(%rsp)
movl $0x100, 0x20(%rsp)      # imm = 0x100
jmp 0x3ed1
leaq 0xa525(%rip), %rax      # 0xe3a0
cmpl $0x10000, 0x1c(%rax)    # imm = 0x10000
jae 0x3e94
leaq 0xa515(%rip), %rax      # 0xe3a0
movl 0x1c(%rax), %eax
movl %eax, 0x8(%rsp)
jmp 0x3e9f
movl $0x10000, %eax          # imm = 0x10000
movl %eax, 0x8(%rsp)
jmp 0x3e9f
movl 0x8(%rsp), %eax
movl %eax, 0x28(%rsp)
movl $0xeff, 0x24(%rsp)      # imm = 0xEFF
movl $0x300, 0x20(%rsp)      # imm = 0x300
jmp 0x3ed1
leaq 0x54d6(%rip), %rdi      # 0x9396
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x10c0
movq $0x0, 0x30(%rsp)
movl 0x64(%rsp), %eax
movl 0x60(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jae 0x3f98
leaq 0xa4ac(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x64(%rsp), %ecx
addl $0x1, %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %al
movb %al, 0x3e(%rsp)
movzbl 0x3f(%rsp), %eax
shll $0x8, %eax
movzbl 0x3e(%rsp), %ecx
addl %ecx, %eax
movw %ax, 0x2e(%rsp)
movzwl 0x2e(%rsp), %eax
movl %eax, %ecx
leaq 0x11d76(%rip), %rax     # 0x15ca0
movq (%rax,%rcx,8), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
je 0x3f96
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
cmpl 0x20(%rsp), %eax
ja 0x3f94
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
cmpl 0x28(%rsp), %eax
ja 0x3f94
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0x2, (%rax,%rcx,8)
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
xorl %edx, %edx
subl %eax, %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x3f96
jmp 0x3f98
cmpq $0x0, 0x30(%rsp)
je 0x41ae
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
cmpl 0x28(%rsp), %eax
ja 0x41ae
movl 0x64(%rsp), %eax
movl 0x60(%rsp), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jae 0x41ae
movl $0x1, 0x40(%rsp)
movl $0x3, 0x48(%rsp)
movl 0x48(%rsp), %ecx
xorl %eax, %eax
cmpl 0x24(%rsp), %ecx
movb %al, 0x7(%rsp)
ja 0x4004
movl 0x64(%rsp), %eax
movl 0x60(%rsp), %ecx
subl 0x48(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
setb %al
movb %al, 0x7(%rsp)
movb 0x7(%rsp), %al
testb $0x1, %al
jne 0x4011
jmp 0x41ac
cmpl $0x0, 0x40(%rsp)
je 0x40df
leaq 0xa37d(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x64(%rsp), %ecx
addl 0x48(%rsp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
leaq 0xa361(%rip), %rcx      # 0xe3a0
movq 0x40(%rcx), %rcx
movq 0x30(%rsp), %rdx
movl (%rdx), %edx
addl 0x48(%rsp), %edx
subl $0x1, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x409f
movl 0x48(%rsp), %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, (%rax,%rcx,8)
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
xorl %edx, %edx
subl %eax, %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x40da
jmp 0x40a1
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
jne 0x40bc
jmp 0x41ac
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
cmpl 0x28(%rsp), %eax
jbe 0x40d2
jmp 0x41ac
movl $0x0, 0x40(%rsp)
jmp 0x41a7
movq 0x58(%rsp), %rax
movl 0x64(%rsp), %ecx
addl 0x48(%rsp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
movq 0x58(%rsp), %rcx
movq 0x30(%rsp), %rdx
movl (%rdx), %edx
addl 0x48(%rsp), %edx
subl $0x1, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x41a0
leaq 0xa283(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rdi
movl 0x64(%rsp), %eax
addq %rax, %rdi
leaq 0xa271(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rsi
movq 0x30(%rsp), %rax
movl (%rax), %eax
addq %rax, %rsi
movl 0x48(%rsp), %eax
movl %eax, %edx
callq 0x1060
cmpl $0x0, %eax
jne 0x4199
movl $0x1, 0x40(%rsp)
movl 0x48(%rsp), %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, (%rax,%rcx,8)
movl 0x64(%rsp), %eax
movq 0x30(%rsp), %rcx
subl (%rcx), %eax
xorl %edx, %edx
subl %eax, %edx
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x419e
jmp 0x40a1
jmp 0x41a5
jmp 0x40a1
jmp 0x41a7
jmp 0x3fdc
jmp 0x41ae
movl 0x4c(%rsp), %eax
leaq 0xa1e7(%rip), %rcx      # 0xe3a0
movl (%rcx), %esi
movl $0x100, %ecx            # imm = 0x100
movl $0xf11, %edx            # imm = 0xF11
cmpl $0x3, %esi
cmovel %edx, %ecx
cmpl %ecx, %eax
jbe 0x41e7
leaq 0x51f0(%rip), %rdi      # 0x93c6
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x10c0
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0x0, (%rax,%rcx,8)
movq 0x50(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl $0x0, 0x4(%rax,%rcx,8)
addq $0x68, %rsp
retq
nopl (%rax)