// File: /workspace/github_c_makefile_star2_O0/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
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl -0xc(%rbp), %eax
shrl $0xc, %eax
movl %eax, -0x24(%rbp)
movl $0x3, %edi
callq 0x12b0
movq %rax, %rcx
movl -0x24(%rbp), %eax
andl %ecx, %eax
movb %al, -0xd(%rbp)
movb $0x0, -0xe(%rbp)
movzbl -0xd(%rbp), %eax
movq %rax, -0x20(%rbp)
subq $0x7, %rax
ja 0xb49b
movq -0x20(%rbp), %rax
leaq 0x3f86(%rip), %rcx      # 0xf274
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl -0xc(%rbp), %eax
shrl $0x14, %eax
movl %eax, %eax
movq %rax, -0x30(%rbp)
movl $0xc, %edi
callq 0x12b0
movq %rax, %rcx
movq -0x30(%rbp), %rax
andq %rcx, %rax
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0xb331
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xab50
jmp 0xb445
cmpl $0x1, -0x14(%rbp)
jne 0xb348
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xabe0
jmp 0xb443
movl -0xc(%rbp), %eax
shrl $0x14, %eax
movl %eax, %eax
movq %rax, -0x40(%rbp)
movl $0x5, %edi
callq 0x12b0
movq %rax, %rcx
movq -0x40(%rbp), %rax
andq %rcx, %rax
movb %al, -0x15(%rbp)
movl -0xc(%rbp), %eax
shrl $0x19, %eax
movl %eax, %eax
movq %rax, -0x38(%rbp)
movl $0x7, %edi
callq 0x12b0
movq %rax, %rcx
movq -0x38(%rbp), %rax
andq %rcx, %rax
movb %al, -0x16(%rbp)
movzbl -0x16(%rbp), %eax
cmpl $0x9, %eax
jne 0xb3a8
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xac10
jmp 0xb441
movzbl -0x16(%rbp), %eax
cmpl $0x8, %eax
jne 0xb3c8
movzbl -0x15(%rbp), %eax
cmpl $0x5, %eax
jne 0xb3c8
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xac20
jmp 0xb43f
movzbl -0x16(%rbp), %eax
cmpl $0x18, %eax
jne 0xb3ec
movzbl -0x15(%rbp), %eax
cmpl $0x2, %eax
jne 0xb3ec
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xac60
movb $0x1, -0xe(%rbp)
jmp 0xb43d
movzbl -0x16(%rbp), %eax
cmpl $0x8, %eax
jne 0xb407
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xad30
movb $0x1, -0xe(%rbp)
jmp 0xb43b
movzbl -0x16(%rbp), %eax
cmpl $0x0, %eax
jne 0xb42b
movzbl -0x15(%rbp), %eax
cmpl $0x2, %eax
jne 0xb42b
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xae00
movb $0x1, -0xe(%rbp)
jmp 0xb439
leaq 0x41fc(%rip), %rdi      # 0xf62e
movb $0x0, %al
callq 0xd690
jmp 0xb43b
jmp 0xb43d
jmp 0xb43f
jmp 0xb441
jmp 0xb443
jmp 0xb445
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xae10
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xaed0
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xafa0
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xb070
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xb120
jmp 0xb4a9
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xb1e0
jmp 0xb4a9
leaq 0x4162(%rip), %rdi      # 0xf604
movb $0x0, %al
callq 0xd690
testb $0x1, -0xe(%rbp)
jne 0xb4bd
movq -0x8(%rbp), %rax
movq (%rax), %rcx
addq $0x4, %rcx
movq %rcx, (%rax)
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)