// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movl %esi, 0x44(%rsp)
movl $0x1, 0x28(%rsp)
movl $0x0, 0x34(%rsp)
cmpq $0x0, 0x48(%rsp)
jne 0x1fb0
leaq 0x7161(%rip), %rdi      # 0x90fd
movb $0x0, %al
callq 0x1040
movl $0x0, 0x54(%rsp)
jmp 0x27c6
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x27(%rsp)
je 0x1fd5
xorl %eax, %eax
movl %eax, %edi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1950
cmpl $0x0, %eax
setne %al
movb %al, 0x27(%rsp)
movb 0x27(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x26(%rsp)
je 0x2002
xorl %esi, %esi
movl %esi, %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x26(%rsp)
movb 0x26(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x25(%rsp)
je 0x2032
xorl %edi, %edi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x25(%rsp)
movb 0x25(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
leaq 0xc35a(%rip), %rax      # 0xe3a0
cmpl $0x0, 0xc(%rax)
je 0x20d0
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x24(%rsp)
je 0x208e
leaq 0xc33c(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rdi
leaq 0xc331(%rip), %rax      # 0xe3a0
movl 0x48(%rax), %eax
subl $0x5, %eax
movl %eax, %eax
addq %rax, %rdi
movl $0x5, %esi
callq 0x1950
cmpl $0x0, %eax
setne %al
movb %al, 0x24(%rsp)
movb 0x24(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x23(%rsp)
je 0x20c3
leaq 0x7076(%rip), %rdi      # 0x9125
movl $0x2, %esi
callq 0x1950
cmpl $0x0, %eax
setne %al
movb %al, 0x23(%rsp)
movb 0x23(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x22(%rsp)
je 0x20ff
leaq 0xc2bc(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl $0x2, %esi
movzbl (%rax), %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x22(%rsp)
movb 0x22(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
movl $0x1, 0x40(%rsp)
movl 0x40(%rsp), %ecx
xorl %eax, %eax
cmpl 0x44(%rsp), %ecx
movb %al, 0x21(%rsp)
jae 0x2130
cmpl $0x0, 0x28(%rsp)
setne %al
movb %al, 0x21(%rsp)
movb 0x21(%rsp), %al
testb $0x1, %al
jne 0x213d
jmp 0x26e4
movq 0x48(%rsp), %rax
movl 0x40(%rsp), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, 0x3c(%rsp)
movq 0x48(%rsp), %rax
movl 0x40(%rsp), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movl %eax, 0x38(%rsp)
cmpl $0x0, 0x3c(%rsp)
jne 0x218c
leaq 0x6fb0(%rip), %rdi      # 0x9128
movb $0x0, %al
callq 0x1040
movl $0x0, 0x54(%rsp)
jmp 0x27c6
cmpl $0x1, 0x3c(%rsp)
jne 0x22b2
cmpl $0x0, 0x38(%rsp)
jne 0x2217
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x20(%rsp)
je 0x21c4
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x20(%rsp)
movb 0x20(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1f(%rsp)
je 0x2205
leaq 0xc1bb(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x40(%rsp), %ecx
movl $0x2, %esi
movzbl (%rax,%rcx), %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x1f(%rsp)
movb 0x1f(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
jmp 0x22ad
movl $0xfffffff8, %eax       # imm = 0xFFFFFFF8
cmpl 0x38(%rsp), %eax
jg 0x22a6
cmpl $-0x1, 0x38(%rsp)
jg 0x22a6
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1e(%rsp)
je 0x2250
xorl %edi, %edi
movl $0x3, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x1e(%rsp)
movb 0x1e(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1d(%rsp)
je 0x2285
movl 0x38(%rsp), %edi
shll $0x1d, %edi
movl $0x3, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x1d(%rsp)
movb 0x1d(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x38(%rsp), %eax
jle 0x22a4
movl 0x38(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x22ab
jmp 0x26aa
jmp 0x22ad
jmp 0x26d1
cmpl $0x2, 0x3c(%rsp)
jne 0x2362
movl $0xffffff00, %eax       # imm = 0xFFFFFF00
cmpl 0x38(%rsp), %eax
jg 0x2358
cmpl $-0x1, 0x38(%rsp)
jg 0x2358
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1c(%rsp)
je 0x22fd
movl $0x20000000, %edi       # imm = 0x20000000
movl $0x3, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x1c(%rsp)
movb 0x1c(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1b(%rsp)
je 0x2337
movl 0x38(%rsp), %eax
andl $0xff, %eax
movl $0x2, %esi
movzbl %al, %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x1b(%rsp)
movb 0x1b(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x38(%rsp), %eax
jle 0x2356
movl 0x38(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x235d
jmp 0x26aa
jmp 0x26cf
movl $0x3, %eax
cmpl 0x3c(%rsp), %eax
jg 0x26a8
cmpl $0xff, 0x3c(%rsp)
jg 0x26a8
cmpl $0x3, 0x3c(%rsp)
jne 0x23be
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x1a(%rsp)
je 0x23ac
movl $0x40000000, %edi       # imm = 0x40000000
movl $0x3, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x1a(%rsp)
movb 0x1a(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
jmp 0x252e
cmpl $0xf, 0x3c(%rsp)
jg 0x24bf
movl $0x2, 0x2c(%rsp)
movl 0x3c(%rsp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
shll $0x1e, %edx
movl %edx, 0x30(%rsp)
cmpl $0xf, 0x3c(%rsp)
jne 0x23f3
movl $0xc0000000, 0x30(%rsp) # imm = 0xC0000000
cmpl $0x6, 0x3c(%rsp)
jl 0x2415
movl 0x30(%rsp), %eax
shrl $0x2, %eax
orl $0xc0000000, %eax       # imm = 0xC0000000
movl %eax, 0x30(%rsp)
movl 0x2c(%rsp), %eax
addl $0x2, %eax
movl %eax, 0x2c(%rsp)
cmpl $0x9, 0x3c(%rsp)
jl 0x2437
movl 0x30(%rsp), %eax
shrl $0x2, %eax
orl $0xc0000000, %eax       # imm = 0xC0000000
movl %eax, 0x30(%rsp)
movl 0x2c(%rsp), %eax
addl $0x2, %eax
movl %eax, 0x2c(%rsp)
cmpl $0xc, 0x3c(%rsp)
jl 0x2459
movl 0x30(%rsp), %eax
shrl $0x2, %eax
orl $0xc0000000, %eax       # imm = 0xC0000000
movl %eax, 0x30(%rsp)
movl 0x2c(%rsp), %eax
addl $0x2, %eax
movl %eax, 0x2c(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x19(%rsp)
je 0x247f
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x3, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x19(%rsp)
movb 0x19(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x18(%rsp)
je 0x24b0
movl 0x30(%rsp), %edi
movl 0x2c(%rsp), %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x18(%rsp)
movb 0x18(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
jmp 0x252c
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x17(%rsp)
je 0x24e5
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x5, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x17(%rsp)
movb 0x17(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x16(%rsp)
je 0x251f
movl 0x3c(%rsp), %eax
andl $0xff, %eax
movl $0x2, %esi
movzbl %al, %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x16(%rsp)
movb 0x16(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
jmp 0x252e
movl $0xffffff00, %eax       # imm = 0xFFFFFF00
cmpl 0x38(%rsp), %eax
jg 0x25c9
cmpl $-0x1, 0x38(%rsp)
jg 0x25c9
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x15(%rsp)
je 0x256b
xorl %edi, %edi
movl $0x1, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x15(%rsp)
movb 0x15(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x14(%rsp)
je 0x25a5
movl 0x38(%rsp), %eax
andl $0xff, %eax
movl $0x2, %esi
movzbl %al, %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x14(%rsp)
movb 0x14(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x38(%rsp), %eax
jle 0x25c4
movl 0x38(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x26a6
movl $0xfffff000, %eax       # imm = 0xFFFFF000
cmpl 0x38(%rsp), %eax
jg 0x26a2
cmpl $0xffffff00, 0x38(%rsp) # imm = 0xFFFFFF00
jge 0x26a2
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x13(%rsp)
je 0x260c
movl $0x80000000, %edi       # imm = 0x80000000
movl $0x1, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x13(%rsp)
movb 0x13(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x12(%rsp)
je 0x2647
movl 0x38(%rsp), %edi
andl $0xf00, %edi            # imm = 0xF00
shll $0x14, %edi
movl $0x4, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x12(%rsp)
movb 0x12(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x11(%rsp)
je 0x2681
movl 0x38(%rsp), %eax
andl $0xff, %eax
movl $0x2, %esi
movzbl %al, %edi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0x11(%rsp)
movb 0x11(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x38(%rsp), %eax
jle 0x26a0
movl 0x38(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x26a4
jmp 0x26aa
jmp 0x26a6
jmp 0x26cd
jmp 0x26aa
movl 0x3c(%rsp), %esi
movl 0x38(%rsp), %edx
leaq 0x6acb(%rip), %rdi      # 0x9184
movb $0x0, %al
callq 0x1040
movl $0x0, 0x54(%rsp)
jmp 0x27c6
jmp 0x26cf
jmp 0x26d1
jmp 0x26d3
movl 0x3c(%rsp), %eax
addl 0x40(%rsp), %eax
movl %eax, 0x40(%rsp)
jmp 0x2114
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x10(%rsp)
je 0x270a
movl $0x60000000, %edi       # imm = 0x60000000
movl $0x5, %esi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0x10(%rsp)
movb 0x10(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0xf(%rsp)
je 0x273a
xorl %edi, %edi
movl $0x2, %esi
callq 0x1b30
cmpl $0x0, %eax
setne %al
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0xe(%rsp)
je 0x2767
xorl %esi, %esi
movl %esi, %edi
callq 0x1ce0
cmpl $0x0, %eax
setne %al
movb %al, 0xe(%rsp)
movb 0xe(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0xd(%rsp)
je 0x2796
xorl %eax, %eax
movl %eax, %edi
xorl %esi, %esi
callq 0x1950
cmpl $0x0, %eax
setne %al
movb %al, 0xd(%rsp)
movb 0xd(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x28(%rsp)
cmpl $0x0, 0x28(%rsp)
je 0x27be
xorl %esi, %esi
subl 0x34(%rsp), %esi
leaq 0x691b(%rip), %rdi      # 0x90d2
movb $0x0, %al
callq 0x1040
movl 0x28(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
addq $0x58, %rsp
retq
nop