// File: /workspace/github_c_makefile_star2_O2/generot[P]VM-0/src/vm/handling.c
// Function: handle_instr
void handle_instr(instr in, double *data_segment, size_s *ip) {
    double lhs = 0, rhs = 0;
    size_s addr;

    if(in.op >= OPC_ADDF && in.op <= OPC_NEQ) {
        lhs = stack_pop();
        rhs = stack_pop();
    }

    switch(in.op) {
    case OPC_PUSH:
        if(in.content_type == INST_ADDR)
            stack_push(in.addr);
        else
            stack_push(in.val);
        
        break;
    case OPC_POP:
        stack_pop();
        break;
    case OPC_DEREF:
        addr = (size_s)stack_pop();
        stack_push(data_segment[addr]);
        break;
    case OPC_STORE:
        data_segment[in.addr] = stack_pop();
        break;
    case OPC_ADDF:
        stack_push(lhs + rhs);
        break;
    case OPC_SUBF:
        stack_push(rhs - lhs);
        break;
    case OPC_MULTF:
        stack_push(lhs * rhs);
        break;
    case OPC_DIVF:
        stack_push(rhs / lhs);
        break;
    case OPC_AND:
        stack_push(lhs && rhs);
        break;
    case OPC_OR:
        stack_push(lhs || rhs);
        break;
    case OPC_GT:
        stack_push(lhs < rhs);
        break;
    case OPC_LT:
        stack_push(lhs > rhs);
        break;
    case OPC_GEQ:
        stack_push(lhs <= rhs);
        break;
    case OPC_LEQ:
        stack_push(lhs >= rhs);
        break;
    case OPC_EQ:
        stack_push(lhs == rhs);
        break;
    case OPC_NEQ:
        stack_push(lhs != rhs);
        break;
    case OPC_JMP:
        *ip = in.addr - 1;
        break;
    case OPC_JNZ:
        lhs = stack_pop();
        if(lhs != 0) *ip = in.addr - 1;

        break;
    case OPC_JEZ:
        lhs = stack_pop();
        if(lhs == 0) *ip = in.addr - 1;

        break;
    case OPC_CALL:
        if(in.content_type == INST_ADDR) {
            double ret_addr = (double)(*ip) + 1;
            // printf("Return address(from OPC_CALL): %lf\n", ret_addr);

            stack_push(ret_addr);
            *ip = in.addr - 1;
        }

        break;
    case OPC_RET:
        lhs = stack_pop();
        *ip = (size_s)lhs - 1;

        break;
    case OPC_SYSCALL:
        handle_syscall(in, data_segment);
        break;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movq %rdi, %r14
movl 0x44(%rsp), %r12d
leal -0x14(%r12), %eax
xorpd %xmm0, %xmm0
xorpd %xmm2, %xmm2
cmpl $0xb, %eax
ja 0x14a4
callq 0x1313
movapd %xmm0, (%rsp)
callq 0x1313
movapd (%rsp), %xmm2
addl $-0x10, %r12d
cmpl $0x15, %r12d
ja 0x163e
leaq 0x40(%rsp), %r15
leaq 0xbe2(%rip), %rax       # 0x20a0
movslq (%rax,%r12,4), %rcx
addq %rax, %rcx
jmpq *%rcx
cmpl $0x1, (%r15)
jne 0x164a
cvtsi2sdq 0x10(%r15), %xmm0
jmp 0x160c
cmpeqsd %xmm0, %xmm2
jmp 0x15e1
cmpltsd %xmm2, %xmm0
jmp 0x15b1
addsd %xmm2, %xmm0
jmp 0x160c
cmplesd %xmm0, %xmm2
jmp 0x15e1
xorpd %xmm1, %xmm1
cmpneqpd %xmm1, %xmm0
cmpneqpd %xmm1, %xmm2
orpd %xmm0, %xmm2
jmp 0x1601
callq 0x1313
cvttsd2si %xmm0, %rax
movsd (%r14,%rax,8), %xmm0
jmp 0x160c
cmpneqsd %xmm0, %xmm2
jmp 0x15e1
callq 0x1313
movq 0x10(%r15), %rax
movsd %xmm0, (%r14,%rax,8)
jmp 0x163e
divsd %xmm2, %xmm0
jmp 0x160c
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x1313
callq 0x1313
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x1634
jp 0x1634
jmp 0x163e
callq 0x1313
cvttsd2si %xmm0, %rax
jmp 0x1638
subsd %xmm2, %xmm0
jmp 0x160c
movq %r14, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x1652
cmplesd %xmm2, %xmm0
movsd 0xadf(%rip), %xmm1      # 0x2098
andpd %xmm0, %xmm1
movapd %xmm1, %xmm0
jmp 0x160c
mulsd %xmm2, %xmm0
jmp 0x160c
callq 0x1313
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x163e
jnp 0x1634
jmp 0x163e
cmpltsd %xmm0, %xmm2
movsd 0xaaf(%rip), %xmm0      # 0x2098
andpd %xmm2, %xmm0
jmp 0x160c
xorpd %xmm1, %xmm1
cmpneqpd %xmm1, %xmm0
cmpneqpd %xmm1, %xmm2
andpd %xmm0, %xmm2
movd %xmm2, %eax
andl $0x1, %eax
cvtsi2sd %eax, %xmm0
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x12c4
cmpl $0x1, (%r15)
jne 0x163e
cvtsi2sdq (%rbx), %xmm0
addsd 0xa69(%rip), %xmm0      # 0x2098
callq 0x12c4
movq 0x10(%r15), %rax
decq %rax
movq %rax, (%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movsd 0x10(%r15), %xmm0
jmp 0x160c