// File: /workspace/github_c_makefile_star2_O3/salextpuru[P]speccy-toochain/src/mhmt/mhmt-emit.c
// Function: emit_megalz
ULONG emit_megalz(struct optchain * optch, ULONG actual_len)
{
    ULONG position;
    LONG length;
    LONG disp;
    LONG max_disp; // maximum encountered displacement
    ULONG varbits,varlen;
    ULONG success = 1;
    max_disp = 0;

    // some checks
    if( !optch ) {
        printf("mhmt-emit.c:emit_megalz() - NULL passed!\n");
        return 0;
    }

    // initialize
    success = success && emit_file(NULL, EMIT_FILE_INIT);
    success = success && emit_byte(0, EMIT_BYTE_INIT);
    success = success && emit_bits(0, EMIT_BITS_INIT);
    // copy first byte as-is
    success = success && emit_file( wrk.indata, 1);
    // go emitting codes
    position = 1;

    while( (position<actual_len) && success ) {
        length = optch[position].code.length;
        disp   = optch[position].code.disp;

        if( length==0 ) {
            printf("mhmt-emit.c:emit_megalz() - encountered stop-code in optimal chain before emitting all data!\n");
            return 0;

        } else if( length==1 ) { // either copy-byte or len=1 code
            if( disp==0 ) { // copy-byte (%1<byte>)
                success = success && emit_bits( 0x80000000, 1 );
                success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );

            } else if( (-8)<=disp && disp<=(-1) ) { // len=1, disp=-1..-8 (%000abc)
                success = success && emit_bits( 0x00000000,   3 );
                success = success && emit_bits( disp<<(32-3), 3 );

                if( max_disp > disp ) max_disp = disp;

            } else
                goto INVALID_CODE_MEGALZ;

        } else if( length==2 ) {
            if( (-256)<=disp && disp<=(-1) ) { // %001<byte>
                success = success && emit_bits( 0x20000000, 3 );
                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );

                if( max_disp > disp ) max_disp = disp;

            } else
                goto INVALID_CODE_MEGALZ;

        } else if( 3<=length && length<=255 ) {
            // length coding
            if( length==3 ) { // %010
                success = success && emit_bits( 0x40000000, 3 );

            } else { // length==4..255, %011
                success = success && emit_bits( 0x60000000, 3 );
                // calculate size of variable bits
                varlen = 0;
                varbits = (length-2)>>1;

                while( varbits ) {
                    varbits >>= 1;
                    varlen++;
                }

                varbits = length-2-(1<<varlen); // prepare length coding
                success = success && emit_bits(       1<<(32-varlen), varlen );
                success = success && emit_bits( varbits<<(32-varlen), varlen );
            }

            // displacement coding
            if( (-256)<=disp && disp<=(-1) ) {
                success = success && emit_bits( 0, 1 );
                success = success && emit_byte( (UBYTE)(0x00ff & disp), EMIT_BYTE_ADD );

                if( max_disp > disp ) max_disp = disp;

            } else if( (-4352)<=disp && disp<(-256) ) {
                success = success && emit_bits( 0x80000000, 1 );
                success = success && emit_bits( (0x0F00&(disp+0x0100))<<20, 4 );
                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );

                if( max_disp > disp ) max_disp = disp;

            } else
                goto INVALID_CODE_MEGALZ;

        } else {
INVALID_CODE_MEGALZ:
            printf("mhmt-emit.c:emit_megalz() - invalid code: length=%d, displacement=%d\n",length,disp);
            return 0;
        }

        position += length;
    }

    // stop-code
    success = success && emit_bits( 0x60100000, 12 );
    success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
    success = success && emit_file( NULL, EMIT_FILE_FINISH );

    if( success )
        printf("Maximum displacement actually used is %d.\n",-max_disp);

    return success;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, 0x10(%rsp)
testq %rdi, %rdi
je 0x15a9
movl %esi, %r14d
xorl %eax, %eax
movl %eax, 0x9f9d(%rip)      # 0xb200
movl %eax, 0xa0a7(%rip)      # 0xb310
movl %eax, 0xa0a5(%rip)      # 0xb314
movl %eax, 0xa0a3(%rip)      # 0xb318
movl %eax, 0xa0a1(%rip)      # 0xb31c
leaq 0xa09e(%rip), %rax      # 0xb320
movq 0x40(%rax), %rdi
movl $0x1, %r12d
movl $0x1, %esi
callq 0x15f2
cmpl $0x2, %r14d
setae %cl
testl %eax, %eax
setne %al
andb %al, %cl
movl $0x0, %ebp
cmpb $0x1, %cl
jne 0x1556
xorl %ebp, %ebp
movl %r14d, 0x8(%rsp)
movl %r12d, %r15d
movq %r15, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %rcx
movl (%rcx,%rax), %r12d
movl 0x4(%rcx,%rax), %r13d
cmpl $0x1, %r12d
je 0x1374
cmpl $0x2, %r12d
je 0x1317
testl %r12d, %r12d
je 0x15e0
leal -0x3(%r12), %eax
cmpl $0xfc, %eax
ja 0x15c8
movl %ebp, 0xc(%rsp)
cmpl $0x3, %r12d
jne 0x13bc
movl $0x40000000, %edi       # imm = 0x40000000
movl $0x3, %esi
jmp 0x140b
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x15c8
movl $0x20000000, %edi       # imm = 0x20000000
movl $0x3, %esi
callq 0x180b
xorl %ebx, %ebx
testl %eax, %eax
je 0x1535
movl 0x9fcd(%rip), %eax      # 0xb310
leaq 0x9ec6(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9fb7(%rip)      # 0xb310
movl $0x1, %ebx
cmpl 0x9fb0(%rip), %eax      # 0xb314
movl 0x8(%rsp), %r14d
je 0x14cf
jmp 0x153a
testl %r13d, %r13d
je 0x14df
cmpl $-0x8, %r13d
jb 0x15c8
xorl %ebx, %ebx
xorl %edi, %edi
movl $0x3, %esi
callq 0x180b
testl %eax, %eax
je 0x13ab
movl %r13d, %edi
shll $0x1d, %edi
movl $0x3, %esi
callq 0x180b
movl %eax, %ebx
cmpl %r13d, %ebp
cmovgel %r13d, %ebp
movl 0x8(%rsp), %r14d
jmp 0x1541
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x3, %esi
callq 0x180b
leal -0x2(%r12), %ecx
bsrl %ecx, %ebx
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %ebx, %ecx
shll %cl, %ebp
xorl %r14d, %r14d
testl %eax, %eax
je 0x1413
movl %ebx, %ecx
negl %ecx
movl $0x1, %edi
shll %cl, %edi
movl %ebx, %esi
callq 0x180b
testl %eax, %eax
je 0x1413
leal (%r12,%rbp), %edi
addl $-0x2, %edi
movl $0x20, %ecx
subl %ebx, %ecx
shll %cl, %edi
movl %ebx, %esi
callq 0x180b
movl %eax, %r14d
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x1445
testl %r14d, %r14d
movl 0xc(%rsp), %ebp
je 0x1533
xorl %ebx, %ebx
xorl %edi, %edi
movl $0x1, %esi
callq 0x180b
testl %eax, %eax
movl 0x8(%rsp), %r14d
jne 0x14a6
jmp 0x153a
leal 0x1100(%r13), %eax
cmpl $0xfff, %eax            # imm = 0xFFF
movl 0xc(%rsp), %ebp
ja 0x15c8
xorl %ebx, %ebx
testl %r14d, %r14d
je 0x1535
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x180b
testl %eax, %eax
movl 0x8(%rsp), %r14d
je 0x153a
movl %r13d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
addl $0x10000000, %edi       # imm = 0x10000000
movl $0x4, %esi
callq 0x180b
testl %eax, %eax
je 0x153a
movl 0x9e64(%rip), %eax      # 0xb310
leaq 0x9d5d(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9e4e(%rip)      # 0xb310
movl $0x1, %ebx
cmpl 0x9e47(%rip), %eax      # 0xb314
jne 0x153a
leaq 0x4d18(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %ebx, %ebx
jmp 0x153a
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x180b
testl %eax, %eax
je 0x15b5
leaq 0x9e23(%rip), %rax      # 0xb320
movq 0x40(%rax), %rax
movb (%rax,%r15), %al
movl 0x9e05(%rip), %ecx      # 0xb310
leaq 0x9cfe(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %eax
movl %eax, 0x9def(%rip)      # 0xb310
movl $0x1, %ebx
cmpl 0x9de8(%rip), %eax      # 0xb314
jne 0x1541
jmp 0x15e9
xorl %ebx, %ebx
movl 0x8(%rsp), %r14d
cmpl %r13d, %ebp
cmovgel %r13d, %ebp
addl %r15d, %r12d
testl %ebx, %ebx
setne %al
cmpl %r14d, %r12d
jae 0x1556
testl %ebx, %ebx
jne 0x12b9
testb %al, %al
je 0x15b5
movl $0x60100000, %edi       # imm = 0x60100000
movl $0xc, %esi
callq 0x180b
testl %eax, %eax
movl $0x0, %ebx
je 0x15b7
xorl %ebx, %ebx
xorl %edi, %edi
xorl %esi, %esi
callq 0x180b
testl %eax, %eax
je 0x15b7
xorl %ebx, %ebx
xorl %edi, %edi
xorl %esi, %esi
callq 0x15f2
testl %eax, %eax
je 0x15b7
negl %ebp
leaq 0x4ab1(%rip), %rdi      # 0x604a
movl %ebp, %esi
xorl %eax, %eax
callq 0x1040
movl $0x1, %ebx
jmp 0x15b7
leaq 0x4b54(%rip), %rdi      # 0x6104
callq 0x1120
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4a35(%rip), %rdi      # 0x6004
xorl %ebx, %ebx
movl %r12d, %esi
movl %r13d, %edx
xorl %eax, %eax
callq 0x1040
jmp 0x15b7
leaq 0x4b46(%rip), %rdi      # 0x612d
jmp 0x15b0
leaq 0x4bfe(%rip), %rdi      # 0x61ee
jmp 0x15b0