// File: /workspace/github_c_makefile_star2_O2/salextpuru[P]speccy-toochain/src/mhmt/mhmt-emit.c
// Function: emit_hrum
ULONG emit_hrum(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_hrum() - 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);

    // manage zx header info
    if( wrk.zxheader ) {
        success = success && emit_file( &wrk.indata[wrk.inlen-5], 5);
        success = success && emit_file( (UBYTE*)"\020\020", 2); // 0x10, 0x10
    }

    // schedule first byte to be placed just after first bitstream word
    success = success && emit_byte( wrk.indata[0], EMIT_BYTE_ADD);
    // 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_hrum() - 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_HRUM;

        } 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_HRUM;

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

            } else if( length<=15 ) {
                varlen=2;
                varbits = (length % 3)<<30; // low 2 bits (except for length==15)

                if( length==15 ) varbits = 0xC0000000;

                if( length>=6 ) {
                    varbits = 0xC0000000 | (varbits>>2);
                    varlen += 2;
                }

                if( length>=9 ) {
                    varbits = 0xC0000000 | (varbits>>2);
                    varlen += 2;
                }

                if( length>=12) {
                    varbits = 0xC0000000 | (varbits>>2);
                    varlen += 2;
                }

                success = success && emit_bits( 0x60000000, 3 );
                success = success && emit_bits( varbits, varlen );

            } else { // 15<length<=255: %01100<len>
                success = success && emit_bits( 0x60000000, 5 );
                success = success && emit_byte( (UBYTE)(length&0x00FF), EMIT_BYTE_ADD );
            }

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

                if( max_disp > disp ) max_disp = disp;

            } else if( (-4096)<=disp && disp<(-256) ) { //%1abcd<disp>
                success = success && emit_bits( 0x80000000, 1 );
                success = success && emit_bits( (0x0F00&disp)<<20, 4 );
                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );

                if( max_disp > disp ) max_disp = disp;

            } else
                goto INVALID_CODE_HRUM;

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

        position += length;
    }

    // stop-code: %01100<0>
    success = success && emit_bits( 0x60000000, 5 );
    success = success && emit_byte( 0x00, EMIT_BYTE_ADD );
    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 0x192e
xorl %ebx, %ebx
pushq $-0x1
popq %rsi
xorl %edi, %edi
callq 0x156d
testl %eax, %eax
je 0x18ed
andl $0x0, 0x8a39(%rip)      # 0xa310
andl $0x0, 0x8a36(%rip)      # 0xa314
pushq $-0x1
popq %rsi
xorl %edi, %edi
callq 0x1733
testl %eax, %eax
setne %bl
leaq 0x8a2c(%rip), %r15      # 0xa320
cmpl $0x0, 0xc(%r15)
sete %al
setne %cl
andb %bl, %cl
cmpb $0x1, %cl
jne 0x1941
movl 0x48(%r15), %edi
addl $-0x5, %edi
addq 0x40(%r15), %rdi
pushq $0x5
popq %rsi
callq 0x156d
testl %eax, %eax
je 0x195e
leaq 0x3751(%rip), %rdi      # 0x5075
pushq $0x2
popq %rsi
callq 0x156d
jmp 0x1946
leaq 0x3950(%rip), %rdi      # 0x5285
callq 0x1110
xorl %ebx, %ebx
jmp 0x1bf5
andb %bl, %al
movzbl %al, %eax
testl %eax, %eax
je 0x195e
movq 0x40(%r15), %rax
movzbl (%rax), %edi
pushq $0x2
popq %rsi
callq 0x1678
movl %eax, %r13d
jmp 0x1961
xorl %r13d, %r13d
xorl %ebp, %ebp
pushq $0x1
popq %rbx
pushq $0x3
popq %r14
cmpl 0xc(%rsp), %ebx
jae 0x1b82
testl %r13d, %r13d
je 0x1b82
movl %ebx, %r13d
movq %r13, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %rcx
movl (%rcx,%rax), %r15d
movl 0x4(%rcx,%rax), %r12d
cmpl $0x1, %r15d
je 0x19f3
cmpl $0x2, %r15d
pushq $0x3
popq %rsi
je 0x19cc
testl %r15d, %r15d
je 0x1c06
leal -0x3(%r15), %eax
cmpl $0xfc, %eax
ja 0x1bdf
cmpl $0x3, %r15d
jne 0x1a2e
movl $0x40000000, %edi       # imm = 0x40000000
jmp 0x1aad
cmpl $0xffffff00, %r12d      # imm = 0xFFFFFF00
jb 0x1bdf
movl $0x20000000, %edi       # imm = 0x20000000
callq 0x1733
testl %eax, %eax
jne 0x1b5f
xorl %r13d, %r13d
jmp 0x1b6e
testl %r12d, %r12d
je 0x1ab4
cmpl $-0x8, %r12d
jb 0x1bdf
xorl %r13d, %r13d
xorl %edi, %edi
movl %r14d, %esi
callq 0x1733
testl %eax, %eax
je 0x1b6e
movl %r12d, %edi
shll $0x1d, %edi
movl %r14d, %esi
callq 0x1733
jmp 0x1b6b
movl $0x60000000, %edi       # imm = 0x60000000
cmpl $0xf, %r15d
ja 0x1ae9
callq 0x1733
testl %eax, %eax
je 0x1b03
movzbl %r15b, %eax
movb $0x3, %cl
divb %cl
movzbl %ah, %eax
movl %eax, %ecx
orl $-0x4, %ecx
shll $0x1c, %ecx
cmpl $0xf, %r15d
movl $0xf0000000, %edx       # imm = 0xF0000000
cmovel %edx, %ecx
shll $0x1e, %eax
xorl %edx, %edx
cmpl $0x6, %r15d
setae %dl
cmovael %ecx, %eax
movl %eax, %ecx
shrl $0x2, %ecx
movl $0xc0000000, %r8d       # imm = 0xC0000000
orl %r8d, %ecx
cmpl $0x9, %r15d
leal 0x2(%rdx,%rdx), %esi
leal 0x4(%rdx,%rdx), %edx
cmovbl %esi, %edx
cmovbl %eax, %ecx
leal 0x2(%rdx), %esi
movl %ecx, %edi
shrl $0x2, %edi
orl %r8d, %edi
cmpl $0xc, %r15d
cmovbl %edx, %esi
cmovbl %ecx, %edi
callq 0x1733
jmp 0x1b05
movl $0x80000000, %edi       # imm = 0x80000000
pushq $0x1
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x1b7d
leaq 0x8850(%rip), %rax      # 0xa320
movq 0x40(%rax), %rax
movzbl (%rax,%r13), %edi
pushq $0x2
popq %rsi
callq 0x1678
movl %eax, %r13d
jmp 0x1b75
pushq $0x5
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x1b03
movzbl %r15b, %edi
pushq $0x2
popq %rsi
callq 0x1678
jmp 0x1b05
xorl %eax, %eax
cmpl $0xffffff00, %r12d      # imm = 0xFFFFFF00
jb 0x1b1b
xorl %r13d, %r13d
testl %eax, %eax
je 0x1b6e
xorl %edi, %edi
pushq $0x1
jmp 0x1b55
leal 0x1000(%r12), %ecx
cmpl $0xeff, %ecx            # imm = 0xEFF
ja 0x1bdf
xorl %r13d, %r13d
testl %eax, %eax
je 0x1b6e
movl $0x80000000, %edi       # imm = 0x80000000
pushq $0x1
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x1b6e
movl %r12d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
pushq $0x4
popq %rsi
callq 0x1733
testl %eax, %eax
je 0x1b6e
movzbl %r12b, %edi
pushq $0x2
popq %rsi
callq 0x1678
movl %eax, %r13d
cmpl %r12d, %ebp
cmovgel %r12d, %ebp
addl %r15d, %ebx
jmp 0x196a
xorl %r13d, %r13d
jmp 0x1b75
xorl %ebx, %ebx
testl %r13d, %r13d
je 0x1bf5
pushq $0x5
popq %rsi
movl $0x60000000, %edi       # imm = 0x60000000
callq 0x1733
testl %eax, %eax
je 0x1bf5
xorl %ebx, %ebx
pushq $0x2
popq %rsi
xorl %edi, %edi
callq 0x1678
testl %eax, %eax
je 0x1bf5
xorl %ebx, %ebx
xorl %edi, %edi
xorl %esi, %esi
callq 0x1733
testl %eax, %eax
je 0x1bf5
xorl %ebx, %ebx
xorl %edi, %edi
xorl %esi, %esi
callq 0x156d
testl %eax, %eax
je 0x1bf5
negl %ebp
leaq 0x3479(%rip), %rdi      # 0x504a
movl %ebp, %esi
xorl %eax, %eax
callq 0x1040
pushq $0x1
popq %rbx
jmp 0x1bf5
leaq 0x3492(%rip), %rdi      # 0x5078
xorl %ebx, %ebx
movl %r15d, %esi
movl %r12d, %edx
xorl %eax, %eax
callq 0x1040
movl %ebx, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x369f(%rip), %rdi      # 0x52ac
jmp 0x1935