// File: /workspace/github_c_makefile_star2_O3/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
pushq %rax
movl %esi, 0x4(%rsp)
testq %rdi, %rdi
je 0x1a2e
movq %rdi, %r14
xorl %r12d, %r12d
movl %r12d, 0x9860(%rip)     # 0xb200
movl %r12d, 0x9969(%rip)     # 0xb310
movl %r12d, 0x9966(%rip)     # 0xb314
movl %r12d, 0x9963(%rip)     # 0xb318
movl %r12d, 0x9960(%rip)     # 0xb31c
leaq 0x995d(%rip), %rbx      # 0xb320
cmpl %r12d, 0xc(%rbx)
je 0x19f6
movl 0x48(%rbx), %edi
addl $-0x5, %edi
addq 0x40(%rbx), %rdi
movl $0x5, %esi
callq 0x15f2
testl %eax, %eax
je 0x1a3d
leaq 0x468d(%rip), %rdi      # 0x6075
movl $0x2, %esi
callq 0x15f2
testl %eax, %eax
je 0x1a3d
movq 0x40(%rbx), %rax
movb (%rax), %al
movl 0x990e(%rip), %ecx      # 0xb310
leaq 0x9807(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %eax
movl %eax, 0x98f8(%rip)      # 0xb310
cmpl 0x98f6(%rip), %eax      # 0xb314
jne 0x1a4f
leaq 0x47c7(%rip), %rdi      # 0x61ee
callq 0x1120
jmp 0x1a3d
leaq 0x4850(%rip), %rdi      # 0x6285
callq 0x1120
xorl %r12d, %r12d
movl %r12d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x0, %ebx
cmpl $0x2, 0x4(%rsp)
jb 0x1d5c
movl $0x1, %r15d
movl $0x0, (%rsp)
movl %r15d, %ebp
movq %rbp, %rax
shlq $0x4, %rax
movl (%r14,%rax), %r15d
movl 0x4(%r14,%rax), %r13d
cmpl $0x1, %r15d
je 0x1adb
cmpl $0x2, %r15d
je 0x1ab8
testl %r15d, %r15d
je 0x1de8
leal -0x3(%r15), %eax
cmpl $0xfc, %eax
ja 0x1d35
cmpl $0x3, %r15d
jne 0x1b1b
movl $0x40000000, %edi       # imm = 0x40000000
movl $0x3, %esi
jmp 0x1ba9
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x1d35
movl $0x20000000, %edi       # imm = 0x20000000
movl $0x3, %esi
callq 0x180b
xorl %ebx, %ebx
jmp 0x1c0d
testl %r13d, %r13d
je 0x1c70
cmpl $-0x8, %r13d
jb 0x1d35
xorl %ebx, %ebx
xorl %edi, %edi
movl $0x3, %esi
callq 0x180b
testl %eax, %eax
je 0x1c48
movl %r13d, %edi
shll $0x1d, %edi
movl $0x3, %esi
callq 0x180b
movl %eax, %ebx
jmp 0x1c48
movl $0x60000000, %edi       # imm = 0x60000000
cmpl $0xf, %r15d
ja 0x1cc6
movl $0x3, %esi
callq 0x180b
testl %eax, %eax
je 0x1d0f
movzbl %r15b, %eax
imull $0xab, %eax, %ecx
shrl $0x9, %ecx
leal (%rcx,%rcx,2), %ecx
subb %cl, %al
movzbl %al, %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 0x180b
movl %eax, %ebx
cmpl $0xfffffeff, %r13d      # imm = 0xFFFFFEFF
jbe 0x1bcc
testl %ebx, %ebx
je 0x1c46
xorl %ebx, %ebx
xorl %edi, %edi
movl $0x1, %esi
jmp 0x1c08
leal 0x1000(%r13), %eax
cmpl $0xf00, %eax            # imm = 0xF00
jae 0x1d35
testl %ebx, %ebx
je 0x1c46
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x180b
xorl %ebx, %ebx
testl %eax, %eax
je 0x1c48
movl %r13d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
movl $0x4, %esi
callq 0x180b
testl %eax, %eax
je 0x1c48
movl 0x96f9(%rip), %eax      # 0xb310
leaq 0x95f2(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x96e3(%rip)      # 0xb310
movl $0x1, %ebx
cmpl 0x96dc(%rip), %eax      # 0xb314
jne 0x1c48
leaq 0x45ad(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %ebx, %ebx
movl (%rsp), %eax
cmpl %r13d, %eax
cmovgel %r13d, %eax
movl %eax, (%rsp)
addl %ebp, %r15d
cmpl 0x4(%rsp), %r15d
jae 0x1d51
testl %ebx, %ebx
jne 0x1a6c
jmp 0x1d51
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x180b
xorl %r12d, %r12d
testl %eax, %eax
je 0x1a3d
leaq 0x968f(%rip), %rax      # 0xb320
movq 0x40(%rax), %rax
movb (%rax,%rbp), %al
movl 0x9672(%rip), %ecx      # 0xb310
leaq 0x956b(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %eax
movl %eax, 0x965c(%rip)      # 0xb310
movl $0x1, %ebx
cmpl 0x9655(%rip), %eax      # 0xb314
jne 0x1c55
jmp 0x1a20
movl $0x5, %esi
callq 0x180b
xorl %ebx, %ebx
testl %eax, %eax
je 0x1bb0
movl 0x9630(%rip), %eax      # 0xb310
leaq 0x9529(%rip), %rcx      # 0xb210
movb %r15b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x961a(%rip)      # 0xb310
cmpl 0x9618(%rip), %eax      # 0xb314
jne 0x1d16
leaq 0x44e9(%rip), %rdi      # 0x61ee
callq 0x1120
jmp 0x1bb0
xorl %ebx, %ebx
jmp 0x1bb0
cmpl $0xfffffeff, %r13d      # imm = 0xFFFFFEFF
ja 0x1bc1
leal 0x1000(%r13), %eax
cmpl $0xf00, %eax            # imm = 0xF00
jb 0x1be2
leaq 0x433c(%rip), %rdi      # 0x6078
xorl %r12d, %r12d
movl %r15d, %esi
movl %r13d, %edx
xorl %eax, %eax
callq 0x1040
jmp 0x1a3d
testl %ebx, %ebx
movl (%rsp), %ebx
je 0x1a3a
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x5, %esi
callq 0x180b
testl %eax, %eax
je 0x1a3a
movl 0x9597(%rip), %eax      # 0xb310
leaq 0x9490(%rip), %rcx      # 0xb210
movb $0x0, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9581(%rip)      # 0xb310
cmpl 0x957f(%rip), %eax      # 0xb314
jne 0x1da3
leaq 0x4450(%rip), %rdi      # 0x61ee
jmp 0x1a35
xorl %r12d, %r12d
xorl %edi, %edi
xorl %esi, %esi
callq 0x180b
testl %eax, %eax
je 0x1a3d
xorl %r12d, %r12d
xorl %edi, %edi
xorl %esi, %esi
callq 0x15f2
testl %eax, %eax
je 0x1a3d
negl %ebx
leaq 0x4276(%rip), %rdi      # 0x604a
movl %ebx, %esi
xorl %eax, %eax
callq 0x1040
movl $0x1, %r12d
jmp 0x1a3d
leaq 0x44bd(%rip), %rdi      # 0x62ac
jmp 0x1a35