// File: /workspace/github_c_makefile_star2_O2/hobo0xcc[P]rve/src/cpu.c
// Function: ExecInstruction
void ExecInstruction(State *state, uint32_t instr) {
    uint8_t opcode = instr & SetNBits(7);
    // If an instruction is compressed.
    if ((opcode & SetNBits(2)) ^ SetNBits(2)) {
        ExecCompressedInstr(state, (uint16_t)(instr & SetNBits(16)));
        return;
    }

    // 32-bit Instruction.
    switch (opcode) {
    case OP_IMM:
        ExecOpImmInstr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case OP_AUIPC:
        ExecAuipc(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case OP_LUI:
        ExecLui(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case OP:
        ExecOpInstr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case JAL:
        ExecJal(state, instr);
        if (state->excepted) return;
        break;
    case JALR:
        ExecJalr(state, instr);
        if (state->excepted) return;
        break;
    case LOAD:
        ExecLoadInstr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case STORE:
        ExecStoreInstr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case BRANCH:
        ExecBranchInstr(state, instr);
        if (state->excepted) return;
        break;
    case OP_IMM_32:
        ExecOpImm32Instr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case OP_32:
        ExecOp32Instr(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case SYSTEM:
        ExecSystemInstr(state, instr);
        if (state->excepted) return;
        break;
    case MISC_MEM:
        ExecMiscMem(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    case AMO:
        ExecAmo(state, instr);
        if (state->excepted) return;
        state->pc += sizeof(instr);
        break;
    default:
        Error("Unknown opcode: 0x%.2x.", opcode);
        break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl %esi, %eax
notl %eax
testb $0x3, %al
jne 0x1ac7
movl %esi, %eax
andl $0x7f, %eax
leal -0x3(%rax), %ecx
shrl $0x2, %ecx
cmpl $0x1c, %ecx
ja 0x1b9f
leaq 0x5553(%rip), %rdx      # 0x7004
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq %rbx, %rdi
callq 0x35fd
jmp 0x1b8b
movzwl %si, %esi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x4747
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x4e27
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x3a7e
movq %rbx, %rdi
callq 0x3be1
jmp 0x1b8b
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x32bb
movq %rbx, %rdi
callq 0x378f
jmp 0x1b8b
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x3322
movq %rbx, %rdi
callq 0x2ce7
jmp 0x1b8b
movq %rbx, %rdi
callq 0x2c85
jmp 0x1b8b
callq 0x4f6d
jmp 0x1b8b
movq %rbx, %rdi
callq 0x59ae
jmp 0x1b8b
movq %rbx, %rdi
callq 0x31d2
jmp 0x1b8b
movq %rbx, %rdi
callq 0x3f73
jmp 0x1b8b
movl %esi, %eax
andl $0xfffff000, %eax       # imm = 0xFFFFF000
movabsq $-0x100000000, %rcx     # imm = 0xFFFFFFFF00000000
orq %rax, %rcx
testl %esi, %esi
cmovnsq %rax, %rcx
shrl $0x4, %esi
andl $0xf8, %esi
movq %rcx, 0x8008(%rbx,%rsi)
cmpb $0x0, 0x8138(%rbx)
jne 0x1b98
addq $0x4, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
leaq 0x58f8(%rip), %rdi      # 0x749e
movl %eax, %esi
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x5ca8