// File: /workspace/github_c_makefile_star2_O0/vtereshkov[P]umka-lang/src/umka_vm.c
// Function: vmAsm
int vmAsm(int ip, const Instruction *code, const DebugInfo *debugPerInstr, char *buf, int size)
{
    const Instruction *instr = &code[ip];
    const DebugInfo *debug = &debugPerInstr[ip];

    char opcodeBuf[DEFAULT_STR_LEN + 1];
    snprintf(opcodeBuf, DEFAULT_STR_LEN + 1, "%s%s", instr->inlineOpcode == OP_SWAP ? "SWAP; " : "", opcodeSpelling[instr->opcode]);
    int chars = snprintf(buf, size, "%09d %6d %28s", ip, debug->line, opcodeBuf);

    if (instr->tokKind != TOK_NONE)
        chars += snprintf(buf + chars, nonneg(size - chars), " %s", lexSpelling(instr->tokKind));

    if (instr->type)
    {
        char typeBuf[DEFAULT_STR_LEN + 1];
        chars += snprintf(buf + chars, nonneg(size - chars), " %s", typeSpelling(instr->type, typeBuf));
    }

    if (instr->typeKind != TYPE_NONE && (!instr->type || instr->opcode == OP_ASSERT_RANGE))
        chars += snprintf(buf + chars, nonneg(size - chars), " %s", typeKindSpelling(instr->typeKind));

    switch (instr->opcode)
    {
        case OP_PUSH:
        {
            if (instr->typeKind == TYPE_PTR || instr->inlineOpcode == OP_DEREF)
                chars += snprintf(buf + chars, nonneg(size - chars), " %p", instr->operand.ptrVal);
            else if (instr->typeKind == TYPE_REAL)
                chars += snprintf(buf + chars, nonneg(size - chars), " %lg", instr->operand.realVal);
            else
                chars += snprintf(buf + chars, nonneg(size - chars), " %lld", (long long int)instr->operand.intVal);
            break;
        }
        case OP_PUSH_REG:
        case OP_POP_REG:                chars += snprintf(buf + chars, nonneg(size - chars), " %s",  regSpelling[instr->operand.intVal]); break;
        case OP_PUSH_ZERO:
        case OP_PUSH_LOCAL_PTR:
        case OP_PUSH_LOCAL:
        case OP_POP:
        case OP_ZERO:
        case OP_ASSIGN:
        case OP_ASSIGN_PARAM:
        case OP_BINARY:
        case OP_CHANGE_REF_CNT_LOCAL:
        case OP_GET_FIELD_PTR:
        case OP_GOTO:
        case OP_GOTO_IF:
        case OP_GOTO_IF_NOT:
        case OP_CALL_INDIRECT:
        case OP_RETURN:                 chars += snprintf(buf + chars, nonneg(size - chars), " %lld",  (long long int)instr->operand.intVal); break;
        case OP_CALL:
        {
            const char *fnName = debugPerInstr[instr->operand.intVal].fnName;
            chars += snprintf(buf + chars, nonneg(size - chars), " %s (%lld)", fnName, (long long int)instr->operand.intVal);
            break;
        }
        case OP_PUSH_LOCAL_PTR_ZERO:
        case OP_GET_ARRAY_PTR:          chars += snprintf(buf + chars, nonneg(size - chars), " %d %d", (int)instr->operand.int32Val[0], (int)instr->operand.int32Val[1]); break;
        case OP_CHANGE_REF_CNT_GLOBAL:
        case OP_ENTER_FRAME:
        case OP_CALL_EXTERN:            chars += snprintf(buf + chars, nonneg(size - chars), " %p",    instr->operand.ptrVal); break;
        case OP_CALL_BUILTIN:           chars += snprintf(buf + chars, nonneg(size - chars), " %s",    builtinSpelling[instr->operand.builtinVal]); break;

        default: break;
    }

    if (instr->inlineOpcode == OP_DEREF)
        chars += snprintf(buf + chars, nonneg(size - chars), "; DEREF");

    return chars;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2e0, %rsp            # imm = 0x2E0
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movq -0x10(%rbp), %rax
movslq -0x4(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movslq -0x4(%rbp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
leaq -0x140(%rbp), %rdi
movq -0x30(%rbp), %rax
movl 0x4(%rax), %edx
leaq 0xf7b9d(%rip), %rcx     # 0x1d91a6
leaq 0xfc71e(%rip), %rax     # 0x1ddd2e
cmpl $0xb, %edx
cmoveq %rax, %rcx
movq -0x30(%rbp), %rax
movl (%rax), %eax
movl %eax, %edx
leaq 0x104f6a(%rip), %rax    # 0x1e6590
movq (%rax,%rdx,8), %r8
movl $0x100, %esi            # imm = 0x100
leaq 0xf2d37(%rip), %rdx     # 0x1d436d
movb $0x0, %al
callq 0x3170
movq -0x20(%rbp), %rdi
movslq -0x24(%rbp), %rsi
movl -0x4(%rbp), %ecx
movq -0x38(%rbp), %rax
movl 0x10(%rax), %r8d
leaq -0x140(%rbp), %r9
leaq 0xfc6d7(%rip), %rdx     # 0x1ddd35
movb $0x0, %al
callq 0x3170
movl %eax, -0x144(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, 0x8(%rax)
je 0xe16d9
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x268(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq %rax, -0x260(%rbp)
movq -0x30(%rbp), %rax
movl 0x8(%rax), %edi
callq 0x1b130
movq -0x268(%rbp), %rdi
movq -0x260(%rbp), %rsi
movq %rax, %rcx
leaq 0xf88dc(%rip), %rdx     # 0x1d9fa2
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xe1750
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x278(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq %rax, -0x270(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x250(%rbp), %rsi
callq 0x22070
movq -0x278(%rbp), %rdi
movq -0x270(%rbp), %rsi
movq %rax, %rcx
leaq 0xf8865(%rip), %rdx     # 0x1d9fa2
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, 0xc(%rax)
je 0xe17d2
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xe176e
movq -0x30(%rbp), %rax
cmpl $0x1b, (%rax)
jne 0xe17d2
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x288(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq %rax, -0x280(%rbp)
movq -0x30(%rbp), %rax
movl 0xc(%rax), %edi
callq 0x23b40
movq -0x288(%rbp), %rdi
movq -0x280(%rbp), %rsi
movq %rax, %rcx
leaq 0xf87e3(%rip), %rdx     # 0x1d9fa2
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
movq -0x30(%rbp), %rax
movl (%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x290(%rbp)
subl $0x25, %eax
ja 0xe1b6a
movq -0x290(%rbp), %rax
leaq 0xfa1e2(%rip), %rcx     # 0x1db9dc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %rax
cmpl $0x10, 0xc(%rax)
je 0xe1817
movq -0x30(%rbp), %rax
cmpl $0xd, 0x4(%rax)
jne 0xe186e
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x298(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x298(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0xfc72f(%rip), %rdx     # 0x1ddf85
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1921
movq -0x30(%rbp), %rax
cmpl $0xf, 0xc(%rax)
jne 0xe18cd
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2a0(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2a0(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movsd 0x18(%rax), %xmm0
leaq 0xfc48b(%rip), %rdx     # 0x1ddd43
movb $0x1, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe191f
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2a8(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2a8(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0xfc681(%rip), %rdx     # 0x1ddf8d
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1921
jmp 0xe1b6c
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2b0(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2b0(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0x104d7b(%rip), %rax    # 0x1e66e0
movq (%rax,%rcx,8), %rcx
leaq 0xf8632(%rip), %rdx     # 0x1d9fa2
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2b8(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2b8(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0xfc5c6(%rip), %rdx     # 0x1ddf8d
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
movq -0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
imulq $0x18, 0x18(%rcx), %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x258(%rbp)
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2c0(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2c0(%rbp), %rdi
movq %rax, %rsi
movq -0x258(%rbp), %rcx
movq -0x30(%rbp), %rax
movq 0x18(%rax), %r8
leaq 0xfc308(%rip), %rdx     # 0x1ddd48
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2c8(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2c8(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movl 0x18(%rax), %ecx
movq -0x30(%rbp), %rax
movl 0x1c(%rax), %r8d
leaq 0xfc2b5(%rip), %rdx     # 0x1ddd53
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2d0(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2d0(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
leaq 0xfc490(%rip), %rdx     # 0x1ddf85
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2d8(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2d8(%rbp), %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, %ecx
leaq 0x104bc6(%rip), %rax    # 0x1e6710
movq (%rax,%rcx,8), %rcx
leaq 0xf844d(%rip), %rdx     # 0x1d9fa2
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
jmp 0xe1b6c
jmp 0xe1b6c
movq -0x30(%rbp), %rax
cmpl $0xd, 0x4(%rax)
jne 0xe1bc0
movq -0x20(%rbp), %rax
movslq -0x144(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x2e0(%rbp)
movl -0x24(%rbp), %eax
subl -0x144(%rbp), %eax
movslq %eax, %rdi
callq 0xe1bd0
movq -0x2e0(%rbp), %rdi
movq %rax, %rsi
leaq 0xfc1ad(%rip), %rdx     # 0x1ddd5a
movb $0x0, %al
callq 0x3170
addl -0x144(%rbp), %eax
movl %eax, -0x144(%rbp)
movl -0x144(%rbp), %eax
addq $0x2e0, %rsp            # imm = 0x2E0
popq %rbp
retq
nop