// File: /workspace/github_c_makefile_star2_O2/hobo0xcc[P]rve/src/cpu.c
// Function: ExecSystemInstr
void ExecSystemInstr(State *state, uint32_t instr) {
    uint8_t funct3 = instr >> 12 & SetNBits(3);
    bool is_pc_written = false;

    switch (funct3) {
    case 0x0: {
        uint32_t funct12 = instr >> 20 & SetNBits(12);
        if (funct12 == 0x00) {
            ExecEcall(state, instr);
        } else if (funct12 == 0x01) {
            ExecEbreak(state, instr);
        } else {
            uint8_t funct5 = instr >> 20 & SetNBits(5);
            uint8_t funct7 = instr >> 25 & SetNBits(7);
            if (funct7 == 0x09) {
                ExecSfencevma(state, instr);
            } else if (funct7 == 0x08 && funct5 == 0x5) {
                ExecWfi(state, instr);
            } else if (funct7 == 0x18 && funct5 == 0x2) {
                ExecMret(state, instr);
                is_pc_written = true;
            } else if (funct7 == 0x08) {
                ExecSret(state, instr);
                is_pc_written = true;
            } else if (funct7 == 0x00 && funct5 == 0x2) {
                ExecUret(state, instr);
                is_pc_written = true;
            } else {
                Error("Unknown instruction: System");
            }
        }
    } break;
    case 0x1:
        ExecCsrrw(state, instr);
        break;
    case 0x2:
        ExecCsrrs(state, instr);
        break;
    case 0x3:
        ExecCsrrc(state, instr);
        break;
    case 0x5:
        ExecCsrrwi(state, instr);
        break;
    case 0x6:
        ExecCsrrsi(state, instr);
        break;
    case 0x7:
        ExecCsrrci(state, instr);
        break;
    default:
        Error("Invalid instruction");
    }

    if (!is_pc_written)
        state->pc += sizeof(instr);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl %esi, %eax
shrl $0xc, %eax
andl $0x7, %eax
leaq 0x232d(%rip), %rcx      # 0x716c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl %esi, %eax
shrl $0x14, %eax
cmpl $0x1, %eax
je 0x4ed7
testl %eax, %eax
jne 0x4ee5
movq %rbx, %rdi
callq 0x4b94
jmp 0x4eef
leaq 0x25bf(%rip), %rdi      # 0x7431
xorl %eax, %eax
callq 0x5ca8
jmp 0x4eef
movq %rbx, %rdi
callq 0x4d18
jmp 0x4eef
movq %rbx, %rdi
callq 0x4d54
jmp 0x4eef
movq %rbx, %rdi
callq 0x4df2
jmp 0x4eef
movq %rbx, %rdi
callq 0x4cdf
jmp 0x4eef
movl %esi, %eax
shrl $0xf, %eax
andl $0x1f, %eax
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
shrl $0x4, %esi
andl $0xf8, %esi
movq %rdx, 0x8008(%rbx,%rsi)
movq %rax, 0x8(%rbx,%rcx,8)
jmp 0x4eef
movq %rbx, %rdi
callq 0x4dc1
jmp 0x4eef
leaq 0x2666(%rip), %rdi      # 0x7544
callq 0x1060
jmp 0x4eef
movl %esi, %ecx
shrl $0x19, %ecx
cmpl $0x9, %ecx
jne 0x4efa
addq $0x4, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
andl $0x1f, %eax
movl %ecx, %edx
xorl $0x8, %edx
movl %eax, %edi
xorl $0x5, %edi
orl %edx, %edi
je 0x4f59
movl %ecx, %edx
xorl $0x18, %edx
movl %eax, %edi
xorl $0x2, %edi
orl %edx, %edi
jne 0x4f27
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x4c29
cmpl $0x8, %ecx
jne 0x4f3a
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x4c80
cmpl $0x2, %eax
sete %al
cmpl $0x2000000, %esi        # imm = 0x2000000
setb %cl
testb %al, %cl
jne 0x4ef3
leaq 0x24f1(%rip), %rdi      # 0x7445
jmp 0x4e72
movq %rbx, %rdi
callq 0x4bff