// File: /workspace/github_c_makefile_star2_O1/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
movl %eax, %ecx
andl $0x7, %ecx
leaq 0x26fc(%rip), %rdx      # 0x816c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl %esi, %eax
shrl $0x14, %eax
cmpl $0x1, %eax
je 0x5bb3
testl %eax, %eax
jne 0x5bc1
movb $0x1, 0x8138(%rbx)
movzbl 0x8148(%rbx), %eax
testl %eax, %eax
je 0x5bff
cmpl $0x3, %eax
je 0x5bf8
cmpl $0x1, %eax
jne 0x5c0d
movl $0x9, %eax
jmp 0x5c04
leaq 0x2969(%rip), %rdi      # 0x8431
xorl %eax, %eax
callq 0x6b70
jmp 0x5ba8
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
movl $0xf8, %edi
andl %edi, %eax
movq 0x8008(%rbx,%rax), %rax
orq %rdx, %rax
jmp 0x5b47
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
movl $0xf8, %edi
andl %edi, %eax
movq 0x8008(%rbx,%rax), %rax
notq %rax
andq %rdx, %rax
jmp 0x5b47
movl %esi, %eax
notl %eax
shrl $0xf, %eax
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
orl $-0x20, %eax
cltq
andq %rdx, %rax
jmp 0x5b92
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
movl $0xf8, %edi
andl %edi, %eax
movq 0x8008(%rbx,%rax), %rax
movq %rax, 0x8(%rbx,%rcx,8)
shrl $0x4, %esi
andl %edi, %esi
jmp 0x5ba0
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 0x5ba8
movl %esi, %eax
shrl $0xf, %eax
andl $0x1f, %eax
movl %esi, %ecx
shrl $0x14, %ecx
movq 0x8(%rbx,%rcx,8), %rdx
orq %rdx, %rax
movq %rax, 0x8(%rbx,%rcx,8)
shrl $0x4, %esi
andl $0xf8, %esi
movq %rdx, 0x8008(%rbx,%rsi)
addq $0x4, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
leaq 0x298a(%rip), %rdi      # 0x8544
callq 0x1060
jmp 0x5ba8
movl %esi, %ecx
shrl $0x19, %ecx
cmpl $0x9, %ecx
je 0x5ba8
andl $0x1f, %eax
movl %ecx, %edx
xorl $0x8, %edx
movl %eax, %edi
xorl $0x5, %edi
orl %edx, %edi
je 0x5c4c
movl %ecx, %edx
xorl $0x18, %edx
movl %eax, %edi
xorl $0x2, %edi
orl %edx, %edi
jne 0x5c16
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x5842
movl $0xb, %eax
jmp 0x5c04
movl $0x8, %eax
movq %rax, 0x8140(%rbx)
jmp 0x5ba8
movb $0x0, 0x8138(%rbx)
jmp 0x5ba8
cmpl $0x8, %ecx
jne 0x5c29
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x58a2
cmpl $0x2, %eax
sete %al
cmpl $0x2000000, %esi        # imm = 0x2000000
setb %cl
testb %al, %cl
jne 0x5bac
leaq 0x27fe(%rip), %rdi      # 0x8445
jmp 0x5ac8
movq %rbx, %rdi
callq 0x5818