// File: /workspace/github_c_makefile_star2_O1/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 0x159f
movl %esi, %ebp
xorl %ebx, %ebx
movl %ebx, 0x9f9e(%rip)      # 0xb200
movl %ebx, 0xa0a8(%rip)      # 0xb310
movl %ebx, 0xa0a6(%rip)      # 0xb314
movl %ebx, 0xa0a4(%rip)      # 0xb318
movl %ebx, 0xa0a2(%rip)      # 0xb31c
leaq 0xa09f(%rip), %rax      # 0xb320
movq 0x40(%rax), %rdi
movl $0x1, %r15d
movl $0x1, %esi
callq 0x15fc
cmpl $0x2, %ebp
setae %cl
testl %eax, %eax
setne %al
andb %al, %cl
cmpb $0x1, %cl
jne 0x1568
xorl %ebx, %ebx
movl %ebp, 0x8(%rsp)
movl %r15d, %r14d
movq %r14, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %rcx
movl (%rcx,%rax), %r15d
movl 0x4(%rcx,%rax), %r13d
cmpl $0x1, %r15d
je 0x136c
cmpl $0x2, %r15d
je 0x130e
testl %r15d, %r15d
je 0x15f3
leal -0x3(%r15), %eax
cmpl $0xfc, %eax
ja 0x15ca
movl %ebx, 0xc(%rsp)
cmpl $0x3, %r15d
jne 0x13b5
movl $0x40000000, %edi       # imm = 0x40000000
movl $0x3, %esi
jmp 0x140f
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x15ca
movl $0x20000000, %edi       # imm = 0x20000000
movl $0x3, %esi
callq 0x1822
xorl %r12d, %r12d
testl %eax, %eax
je 0x153c
movl 0x9fd5(%rip), %eax      # 0xb310
leaq 0x9ece(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9fbf(%rip)      # 0xb310
movl $0x1, %r12d
cmpl 0x9fb7(%rip), %eax      # 0xb314
movl 0x8(%rsp), %ebp
je 0x14d1
jmp 0x1540
testl %r13d, %r13d
je 0x14e2
cmpl $-0x8, %r13d
jb 0x15ca
xorl %r12d, %r12d
xorl %edi, %edi
movl $0x3, %esi
callq 0x1822
testl %eax, %eax
je 0x13a5
movl %r13d, %edi
shll $0x1d, %edi
movl $0x3, %esi
callq 0x1822
movl %eax, %r12d
cmpl %r13d, %ebx
cmovgel %r13d, %ebx
movl 0x8(%rsp), %ebp
jmp 0x1547
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x3, %esi
callq 0x1822
leal -0x2(%r15), %ecx
bsrl %ecx, %r12d
xorl %ebp, %ebp
cmpl $0x2, %ecx
cmovbl %ebp, %r12d
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl %r12d, %ecx
shll %cl, %ebx
testl %eax, %eax
je 0x1416
movl %r12d, %ecx
negl %ecx
movl $0x1, %edi
shll %cl, %edi
movl %r12d, %esi
callq 0x1822
testl %eax, %eax
je 0x1416
leal (%rbx,%r15), %edi
addl $-0x2, %edi
movl $0x20, %ecx
subl %r12d, %ecx
shll %cl, %edi
movl %r12d, %esi
callq 0x1822
movl %eax, %ebp
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x1447
testl %ebp, %ebp
movl 0xc(%rsp), %ebx
je 0x1539
xorl %r12d, %r12d
xorl %edi, %edi
movl $0x1, %esi
callq 0x1822
testl %eax, %eax
movl 0x8(%rsp), %ebp
jne 0x14a7
jmp 0x1540
leal 0x1100(%r13), %eax
cmpl $0xfff, %eax            # imm = 0xFFF
movl 0xc(%rsp), %ebx
ja 0x15ca
xorl %r12d, %r12d
testl %ebp, %ebp
je 0x153c
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1822
testl %eax, %eax
movl 0x8(%rsp), %ebp
je 0x1540
movl %r13d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
addl $0x10000000, %edi       # imm = 0x10000000
movl $0x4, %esi
callq 0x1822
testl %eax, %eax
je 0x1540
movl 0x9e63(%rip), %eax      # 0xb310
leaq 0x9d5c(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9e4d(%rip)      # 0xb310
movl $0x1, %r12d
cmpl 0x9e45(%rip), %eax      # 0xb314
jne 0x1540
leaq 0x4d16(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %r12d, %r12d
jmp 0x1540
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1822
xorl %r12d, %r12d
testl %eax, %eax
je 0x1547
leaq 0x9e21(%rip), %rax      # 0xb320
movq 0x40(%rax), %rax
movb (%rax,%r14), %al
movl 0x9e03(%rip), %ecx      # 0xb310
leaq 0x9cfc(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %eax
movl %eax, 0x9ded(%rip)      # 0xb310
cmpl 0x9deb(%rip), %eax      # 0xb314
jne 0x1560
leaq 0x4cbc(%rip), %rdi      # 0x61ee
callq 0x1120
jmp 0x1547
xorl %r12d, %r12d
movl 0x8(%rsp), %ebp
cmpl %r13d, %ebx
cmovgel %r13d, %ebx
addl %r14d, %r15d
testl %r12d, %r12d
setne %al
cmpl %ebp, %r15d
jae 0x1568
testl %r12d, %r12d
jne 0x12b1
jmp 0x1568
movl $0x1, %r12d
jmp 0x1547
testb %al, %al
je 0x15af
movl $0x60100000, %edi       # imm = 0x60100000
movl $0xc, %esi
callq 0x1822
testl %eax, %eax
je 0x15af
xorl %ebp, %ebp
xorl %edi, %edi
xorl %esi, %esi
callq 0x1822
testl %eax, %eax
je 0x15b1
xorl %edi, %edi
xorl %esi, %esi
callq 0x15fc
testl %eax, %eax
setne %bpl
jmp 0x15b1
leaq 0x4b5e(%rip), %rdi      # 0x6104
callq 0x1120
xorl %ebp, %ebp
jmp 0x15e0
xorl %ebp, %ebp
testb %bpl, %bpl
je 0x15e0
negl %ebx
leaq 0x4a8b(%rip), %rdi      # 0x604a
movl %ebx, %esi
xorl %eax, %eax
callq 0x1040
jmp 0x15e0
leaq 0x4a33(%rip), %rdi      # 0x6004
xorl %ebp, %ebp
movl %r15d, %esi
movl %r13d, %edx
xorl %eax, %eax
callq 0x1040
movzbl %bpl, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4b33(%rip), %rdi      # 0x612d
jmp 0x15a6