// File: /workspace/github_c_makefile_star2_O2/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
movl %esi, 0xc(%rsp)
movq %rdi, 0x10(%rsp)
testq %rdi, %rdi
je 0x14d4
movq $0x0, (%rsp)
pushq $-0x1
popq %rsi
xorl %edi, %edi
callq 0x156d
movl $0x0, %r15d
testl %eax, %eax
je 0x129d
andl $0x0, 0x90a1(%rip)      # 0xa310
andl $0x0, 0x909e(%rip)      # 0xa314
xorl %r15d, %r15d
pushq $-0x1
popq %rsi
xorl %edi, %edi
callq 0x1733
testl %eax, %eax
je 0x129d
leaq 0x9092(%rip), %rax      # 0xa320
movq 0x40(%rax), %rdi
pushq $0x1
popq %rsi
callq 0x156d
movl %eax, %r15d
pushq $0x1
popq %rbx
pushq $0x3
popq %rsi
cmpl 0xc(%rsp), %ebx
jae 0x14e5
testl %r15d, %r15d
je 0x14e5
movl %ebx, %r14d
movq %r14, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %rcx
movl (%rcx,%rax), %r13d
movl 0x4(%rcx,%rax), %r12d
cmpl $0x1, %r13d
je 0x1329
cmpl $0x2, %r13d
je 0x1302
testl %r13d, %r13d
je 0x1561
leal -0x3(%r13), %eax
cmpl $0xfc, %eax
ja 0x1538
cmpl $0x3, %r13d
jne 0x1372
movl $0x40000000, %edi       # imm = 0x40000000
jmp 0x13cf
cmpl $0xffffff00, %r12d      # imm = 0xFFFFFF00
jb 0x1538
movl $0x20000000, %edi       # imm = 0x20000000
callq 0x1733
testl %eax, %eax
jne 0x13f4
xorl %r15d, %r15d
jmp 0x1403
testl %r12d, %r12d
je 0x1481
cmpl $-0x8, %r12d
jb 0x1538
xorl %r15d, %r15d
xorl %edi, %edi
movl %esi, %ebp
callq 0x1733
testl %eax, %eax
je 0x135c
movl %r12d, %edi
shll $0x1d, %edi
movl %ebp, %esi
callq 0x1733
movl %eax, %r15d
movq (%rsp), %rax
cmpl %r12d, %eax
cmovgel %r12d, %eax
movq %rax, (%rsp)
movl %ebp, %esi
jmp 0x14cc
movl $0x60000000, %edi       # imm = 0x60000000
callq 0x1733
leal -0x2(%r13), %edx
xorl %r15d, %r15d
movl %edx, %ecx
cmpl $0x2, %ecx
jb 0x1391
shrl %ecx
incl %r15d
jmp 0x1385
pushq $-0x1
popq %r14
movl %r15d, %ecx
shll %cl, %r14d
xorl %ebp, %ebp
testl %eax, %eax
je 0x13d6
movl %edx, 0x8(%rsp)
movl %r15d, %ecx
negl %ecx
pushq $0x1
popq %rdi
shll %cl, %edi
movl %r15d, %esi
callq 0x1733
testl %eax, %eax
je 0x13d6
addl 0x8(%rsp), %r14d
pushq $0x20
popq %rcx
subl %r15d, %ecx
shll %cl, %r14d
movl %r14d, %edi
movl %r15d, %esi
callq 0x1733
movl %eax, %ebp
cmpl $0xffffff00, %r12d      # imm = 0xFFFFFF00
jb 0x141a
xorl %r15d, %r15d
testl %ebp, %ebp
je 0x1403
xorl %edi, %edi
pushq $0x1
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x1403
movzbl %r12b, %edi
pushq $0x2
popq %rsi
callq 0x1678
movl %eax, %r15d
movq (%rsp), %rax
cmpl %r12d, %eax
cmovgel %r12d, %eax
movq %rax, (%rsp)
pushq $0x3
popq %rsi
jmp 0x14cc
leal 0x1100(%r12), %eax
cmpl $0xfff, %eax            # imm = 0xFFF
pushq $0x3
popq %rsi
ja 0x1538
xorl %r15d, %r15d
testl %ebp, %ebp
je 0x14bd
movl $0x80000000, %edi       # imm = 0x80000000
pushq $0x1
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x14ba
movl %r12d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
addl $0x10000000, %edi       # imm = 0x10000000
pushq $0x4
popq %rsi
callq 0x1733
testl %eax, %eax
pushq $0x3
popq %rsi
je 0x14bd
movzbl %r12b, %edi
pushq $0x2
popq %rsi
callq 0x1678
pushq $0x3
popq %rsi
movl %eax, %r15d
jmp 0x14bd
movl $0x80000000, %edi       # imm = 0x80000000
pushq $0x1
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x14b2
leaq 0x8e87(%rip), %rax      # 0xa320
movq 0x40(%rax), %rax
movzbl (%rax,%r14), %edi
pushq $0x2
popq %rsi
callq 0x1678
movl %eax, %r15d
jmp 0x1412
xorl %r15d, %r15d
jmp 0x1412
pushq $0x3
popq %rsi
movq (%rsp), %rax
cmpl %r12d, %eax
cmovgel %r12d, %eax
movq %rax, (%rsp)
addl %r13d, %ebx
jmp 0x12a3
leaq 0x3c29(%rip), %rdi      # 0x5104
callq 0x1110
xorl %r14d, %r14d
jmp 0x154f
xorl %r14d, %r14d
testl %r15d, %r15d
je 0x154f
pushq $0xc
popq %rsi
movl $0x60100000, %edi       # imm = 0x60100000
callq 0x1733
testl %eax, %eax
je 0x154f
xorl %r14d, %r14d
xorl %edi, %edi
xorl %esi, %esi
callq 0x1733
testl %eax, %eax
je 0x154f
xorl %r14d, %r14d
xorl %edi, %edi
xorl %esi, %esi
callq 0x156d
testl %eax, %eax
je 0x154f
movq (%rsp), %rsi
negl %esi
leaq 0x3b1f(%rip), %rdi      # 0x504a
xorl %eax, %eax
callq 0x1040
pushq $0x1
popq %r14
jmp 0x154f
leaq 0x3ac5(%rip), %rdi      # 0x5004
xorl %r14d, %r14d
movl %r13d, %esi
movl %r12d, %edx
xorl %eax, %eax
callq 0x1040
movl %r14d, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3bc5(%rip), %rdi      # 0x512d
jmp 0x14db