// File: /workspace/github_c_makefile_star2_O1/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 0x1a24
movq %rdi, %r14
xorl %r15d, %r15d
movl %r15d, 0x9839(%rip)     # 0xb200
movl %r15d, 0x9942(%rip)     # 0xb310
movl %r15d, 0x993f(%rip)     # 0xb314
movl %r15d, 0x993c(%rip)     # 0xb318
movl %r15d, 0x9939(%rip)     # 0xb31c
leaq 0x9936(%rip), %r12      # 0xb320
xorl %eax, %eax
cmpl %r15d, 0xc(%r12)
sete %cl
je 0x1a37
movl 0x48(%r12), %edi
addl $-0x5, %edi
addq 0x40(%r12), %rdi
movl $0x5, %esi
callq 0x15fc
testl %eax, %eax
je 0x1a3c
leaq 0x465d(%rip), %rdi      # 0x6075
movl $0x2, %esi
callq 0x15fc
jmp 0x1a39
leaq 0x485a(%rip), %rdi      # 0x6285
callq 0x1120
xorl %ebp, %ebp
jmp 0x1dd1
movb %cl, %al
movl %eax, %r15d
xorl %ebx, %ebx
testl %r15d, %r15d
je 0x1a7c
movq 0x40(%r12), %rax
movb (%rax), %al
movl 0x98c0(%rip), %ecx      # 0xb310
leaq 0x97b9(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %ecx
movl %ecx, 0x98aa(%rip)      # 0xb310
movb $0x1, %al
cmpl 0x98a6(%rip), %ecx      # 0xb314
jne 0x1a7e
leaq 0x4777(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %eax, %eax
cmpl $0x2, 0x4(%rsp)
setb %cl
movl %eax, %edx
xorb $0x1, %dl
orb %cl, %dl
jne 0x1d59
movl $0x1, %r15d
xorl %ebx, %ebx
movl %r15d, %ebp
movq %rbp, %rax
shlq $0x4, %rax
movl (%r14,%rax), %r15d
movl 0x4(%r14,%rax), %r13d
cmpl $0x1, %r15d
je 0x1b0b
cmpl $0x2, %r15d
je 0x1ae7
testl %r15d, %r15d
je 0x1e04
leal -0x3(%r15), %eax
cmpl $0xfc, %eax
ja 0x1dbb
cmpl $0x3, %r15d
jne 0x1b4d
movl $0x40000000, %edi       # imm = 0x40000000
movl $0x3, %esi
jmp 0x1bde
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x1dbb
movl $0x20000000, %edi       # imm = 0x20000000
movl $0x3, %esi
callq 0x1822
xorl %r12d, %r12d
jmp 0x1cf2
testl %r13d, %r13d
je 0x1be8
cmpl $-0x8, %r13d
jb 0x1dbb
xorl %r12d, %r12d
xorl %edi, %edi
movl $0x3, %esi
callq 0x1822
testl %eax, %eax
je 0x1d2f
movl %r13d, %edi
shll $0x1d, %edi
movl $0x3, %esi
callq 0x1822
movl %eax, %r12d
jmp 0x1d2f
movl $0x60000000, %edi       # imm = 0x60000000
cmpl $0xf, %r15d
jg 0x1c49
movl $0x3, %esi
callq 0x1822
testl %eax, %eax
je 0x1c90
movl %r15d, %eax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rcx, %rax
shrq $0x21, %rax
leal (%rax,%rax,2), %eax
movl %r15d, %ecx
subl %eax, %ecx
movl %ecx, %eax
orl $-0x4, %eax
shll $0x1c, %eax
cmpl $0xf, %r15d
movl $0xf0000000, %edx       # imm = 0xF0000000
cmovel %edx, %eax
shll $0x1e, %ecx
xorl %edx, %edx
cmpl $0x6, %r15d
setge %dl
cmovgel %eax, %ecx
movl %ecx, %eax
shrl $0x2, %eax
movl $0xc0000000, %r8d       # imm = 0xC0000000
orl %r8d, %eax
cmpl $0x9, %r15d
leal 0x2(%rdx,%rdx), %esi
leal 0x4(%rdx,%rdx), %edx
cmovll %esi, %edx
cmovll %ecx, %eax
leal 0x2(%rdx), %esi
movl %eax, %edi
shrl $0x2, %edi
orl %r8d, %edi
cmpl $0xc, %r15d
cmovll %edx, %esi
cmovll %eax, %edi
callq 0x1822
jmp 0x1c92
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1822
xorl %r12d, %r12d
testl %eax, %eax
je 0x1d36
leaq 0x9717(%rip), %rax      # 0xb320
movq 0x40(%rax), %rax
movb (%rax,%rbp), %al
movl 0x96fa(%rip), %ecx      # 0xb310
leaq 0x95f3(%rip), %rdx      # 0xb210
movb %al, (%rcx,%rdx)
leal 0x1(%rcx), %eax
movzbl %al, %eax
movl %eax, 0x96e4(%rip)      # 0xb310
cmpl 0x96e2(%rip), %eax      # 0xb314
jne 0x1d51
leaq 0x45af(%rip), %rdi      # 0x61ee
callq 0x1120
jmp 0x1d36
movl $0x5, %esi
callq 0x1822
movl %eax, %ecx
xorl %eax, %eax
testl %ecx, %ecx
je 0x1c92
movl 0x96af(%rip), %eax      # 0xb310
leaq 0x95a8(%rip), %rcx      # 0xb210
movb %r15b, (%rax,%rcx)
incl %eax
movzbl %al, %ecx
movl %ecx, 0x9699(%rip)      # 0xb310
movl $0x1, %eax
cmpl 0x9692(%rip), %ecx      # 0xb314
jne 0x1c92
leaq 0x4563(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %eax, %eax
cmpl $0xffffff00, %r13d      # imm = 0xFFFFFF00
jb 0x1caf
testl %eax, %eax
je 0x1d2c
xorl %r12d, %r12d
xorl %edi, %edi
movl $0x1, %esi
jmp 0x1ced
leal 0x1000(%r13), %ecx
cmpl $0xeff, %ecx            # imm = 0xEFF
ja 0x1dbb
xorl %r12d, %r12d
testl %eax, %eax
je 0x1d2f
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1822
testl %eax, %eax
je 0x1d2f
movl %r13d, %edi
shll $0x14, %edi
andl $0xf0000000, %edi       # imm = 0xF0000000
movl $0x4, %esi
callq 0x1822
testl %eax, %eax
je 0x1d2f
movl 0x9614(%rip), %eax      # 0xb310
leaq 0x950d(%rip), %rcx      # 0xb210
movb %r13b, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x95fe(%rip)      # 0xb310
movl $0x1, %r12d
cmpl 0x95f6(%rip), %eax      # 0xb314
jne 0x1d2f
leaq 0x44c7(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %r12d, %r12d
cmpl %r13d, %ebx
cmovgel %r13d, %ebx
addl %ebp, %r15d
testl %r12d, %r12d
setne %al
cmpl 0x4(%rsp), %r15d
jae 0x1d59
testl %r12d, %r12d
jne 0x1a9b
jmp 0x1d59
movl $0x1, %r12d
jmp 0x1d36
testb %al, %al
je 0x1da0
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x5, %esi
callq 0x1822
testl %eax, %eax
je 0x1da0
movl 0x959a(%rip), %eax      # 0xb310
leaq 0x9493(%rip), %rcx      # 0xb210
movb $0x0, (%rax,%rcx)
incl %eax
movzbl %al, %eax
movl %eax, 0x9584(%rip)      # 0xb310
cmpl 0x9582(%rip), %eax      # 0xb314
jne 0x1de4
leaq 0x4453(%rip), %rdi      # 0x61ee
callq 0x1120
xorl %ebp, %ebp
testb %bpl, %bpl
je 0x1dd1
negl %ebx
leaq 0x429a(%rip), %rdi      # 0x604a
movl %ebx, %esi
xorl %eax, %eax
callq 0x1040
jmp 0x1dd1
leaq 0x42b6(%rip), %rdi      # 0x6078
xorl %ebp, %ebp
movl %r15d, %esi
movl %r13d, %edx
xorl %eax, %eax
callq 0x1040
movzbl %bpl, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %ebp, %ebp
xorl %edi, %edi
xorl %esi, %esi
callq 0x1822
testl %eax, %eax
je 0x1da2
xorl %edi, %edi
xorl %esi, %esi
callq 0x15fc
testl %eax, %eax
setne %bpl
jmp 0x1da2
leaq 0x44a1(%rip), %rdi      # 0x62ac
jmp 0x1a2b