// File: /workspace/github_c_makefile_star2_O3/alexj136[P]minijit/src/icode_interpreter.c
// Function: ICodeInterpreterState_step
void ICodeInterpreterState_step(ICodeInterpreterState *state) {

    int initial_prog_counter_value = (state->registers)[PROGRAM_COUNTER];

    ICodeOperation *current =
            ICodeOperationVector_get(state->code, initial_prog_counter_value);

    Opcode opc = current->opc;
    int arg1   = current->arg1;
    int arg2   = current->arg2;

    if(opc == MOVE) {

        // Do the move
        (state->registers)[arg2] = (state->registers)[arg1];

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == LOAD) {

        // Check stack bounds
        ICodeInterpreterState_check_stack_bounds((state->registers)[arg1]);

        // Do the load
        (state->registers)[arg2] = (state->stack)[(state->registers)[arg1]];

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == STORE) {

        // Check stack bounds
        ICodeInterpreterState_check_stack_bounds((state->registers)[arg2]);

        // Do the store
        (state->stack)[(state->registers)[arg2]] = (state->registers)[arg1];

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == ADD) {

        // Do the addition
        (state->registers)[arg1] =
                (state->registers)[arg1] + (state->registers)[arg2];

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == SUB) {

        // Do the subtraction
        (state->registers)[arg1] =
                (state->registers)[arg1] - (state->registers)[arg2];

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == LOADIMM) {

        // Do the load immediate
        (state->registers)[arg2] = arg1;

        // Increment the program counter
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == JUMP) {

        // Set the program counter at the target label
        (state->registers)[PROGRAM_COUNTER] =
                ICodeInterpreterState_lookup_label_address(state, arg1);
    }
    else if(opc == JUMPCOND) {

        // Based on the condition, optionally set the program counter at the
        // target label, or just advance to the next instruction.
        if((state->registers)[arg2] < 1) {
            (state->registers)[PROGRAM_COUNTER] =
                ICodeInterpreterState_lookup_label_address(state, arg1);
        }
        else {
            (state->registers)[PROGRAM_COUNTER]++;
        }
    }
    else if(opc == JUMPLINK) {

        // Store the address of the next instruction in the return address
        // register
        (state->registers)[RETURN_ADDRESS] =
                (state->registers)[PROGRAM_COUNTER] + 1;

        // Set the program counter at the target label
        (state->registers)[PROGRAM_COUNTER] =
                ICodeInterpreterState_lookup_label_address(state, arg1);
    }
    else if(opc == JUMPADDR) {

        // Set the program counter at the address in the register
        (state->registers)[PROGRAM_COUNTER] = (state->registers)[arg1];
    }
    else if(opc == LABEL) {

        // Labels have no effect other than being jump destinations. Just
        // increment the program counter.
        (state->registers)[PROGRAM_COUNTER]++;
    }
    else if(opc == HALT) {

        // Do nothing - we've halted
    }
    else {
        ERROR("Opcode not recognised");
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x1f40, %rsp           # imm = 0x1F40
movq %rdi, %rbx
movq (%rdi), %rdi
movq 0x10(%rbx), %rax
movl 0xc(%rax), %esi
callq 0x144a1
movl (%rax), %edx
cmpq $0xb, %rdx
ja 0x162bc
movl 0x4(%rax), %ecx
movslq %ecx, %r14
movslq 0x8(%rax), %r15
leaq 0x65a7(%rip), %rax      # 0x1c784
movslq (%rax,%rdx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movq 0x10(%rbx), %rax
movl (%rax,%r14,4), %ecx
jmp 0x1627a
movq 0x10(%rbx), %rax
jmp 0x16295
movq 0x10(%rbx), %rax
movl (%rax,%r15,4), %ecx
addl %ecx, (%rax,%r14,4)
jmp 0x16295
movq 0x10(%rbx), %rax
movl 0xc(%rax), %ecx
incl %ecx
movl %ecx, 0x8(%rax)
jmp 0x1629a
movq 0x10(%rbx), %rax
movl (%rax,%r14,4), %edi
callq 0x1603b
movq 0x8(%rbx), %rax
movq 0x10(%rbx), %rcx
movslq (%rcx,%r14,4), %rdx
movl (%rax,%rdx,4), %eax
movl %eax, (%rcx,%r15,4)
jmp 0x1625d
movq 0x10(%rbx), %rax
movl (%rax,%r15,4), %edi
callq 0x1603b
movq 0x8(%rbx), %rax
movq 0x10(%rbx), %rcx
movl (%rcx,%r14,4), %edx
movslq (%rcx,%r15,4), %rsi
movl %edx, (%rax,%rsi,4)
incl 0xc(%rcx)
jmp 0x162ac
movq 0x10(%rbx), %rax
jmp 0x1629a
movq 0x10(%rbx), %rax
movl (%rax,%r15,4), %ecx
subl %ecx, (%rax,%r14,4)
jmp 0x16295
movq 0x10(%rbx), %rax
movl %ecx, (%rax,%r15,4)
jmp 0x16295
movq 0x10(%rbx), %rax
movl (%rax,%r14,4), %ecx
jmp 0x162a9
movq 0x10(%rbx), %rax
cmpl $0x0, (%rax,%r15,4)
jle 0x1629a
incl 0xc(%rax)
jmp 0x162ac
movq 0x18(%rbx), %rcx
movslq 0x20(%rbx), %rdx
subq %rdx, %r14
movl (%rcx,%r14,4), %ecx
movl %ecx, 0xc(%rax)
addq $0x1f40, %rsp           # imm = 0x1F40
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4d41(%rip), %rdi      # 0x1b004
leaq 0x64ea(%rip), %rsi      # 0x1c7b4
leaq 0x6609(%rip), %rcx      # 0x1c8da
movl $0x12a, %edx            # imm = 0x12A
xorl %eax, %eax
callq 0x6100
leaq 0x4d48(%rip), %rdi      # 0x1b02c
leaq 0x660a(%rip), %rsi      # 0x1c8f5
xorl %eax, %eax
callq 0x6100
leaq -0x1f60(%rbp), %rbx
movq %rbx, %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x60e0
movl %eax, %r14d
movq %rbx, %rdi
movl %eax, %esi
callq 0x60b0
movq %rax, %rbx
leaq 0x4ef9(%rip), %rdi      # 0x1b216
callq 0x6070
testl %r14d, %r14d
jle 0x1634a
movl %r14d, %r15d
leaq 0x4cfb(%rip), %r14      # 0x1b02c
xorl %r12d, %r12d
movq (%rbx,%r12,8), %rsi
movq %r14, %rdi
xorl %eax, %eax
callq 0x6100
incq %r12
cmpq %r12, %r15
jne 0x16334
movl $0x1, %edi
callq 0x61a0