// File: /workspace/github_c_makefile_star2_O0/hobo0xcc[P]rve/src/cpu.c
// Function: HandleTrap
void HandleTrap(State *state, uint64_t instr_addr) {
    uint8_t prev_mode = state->mode;
    uint64_t cause = state->exception_code;
    // printf("Trap: addr: 0x%llx, cause: 0x%llx\n", instr_addr, cause);
    uint64_t mdeleg = MEDELEG;
    if (cause & SetOneBit(63)) {
        mdeleg = MIDELEG;
    }
    if (state->mode <= SUPERVISOR && state->csr[mdeleg] >> (cause & 0xffff) & 1) {
        state->mode = SUPERVISOR;
        state->csr[SEPC] = instr_addr;
        uint64_t vector = 0;
        if (ReadCSR(state, STVEC, 0, 0) == 1) {
            vector = 4 * (cause & SetNBits(63));
        }
        state->pc = (state->csr[STVEC] & ~1) + vector;
        state->csr[SCAUSE] = cause;
        state->csr[STVAL] = 0;
        WriteCSR(state, SSTATUS, 5, 5, ReadCSR(state, SSTATUS, 1, 1));
        WriteCSR(state, SSTATUS, 1, 1, 0);
        if (prev_mode == USER) {
            WriteCSR(state, SSTATUS, 8, 8, 0);
        } else {
            WriteCSR(state, SSTATUS, 8, 8, 1);
        }
    } else {
        state->mode = MACHINE;
        state->csr[MEPC] = instr_addr;
        uint64_t vector = 0;
        if (ReadCSR(state, MTVEC, 0, 0) == 1) {
            vector = 4 * (cause & SetNBits(63));
        }
        state->pc = (state->csr[MTVEC] & ~1) + vector;
        state->csr[MCAUSE] = cause;
        state->csr[MTVAL] = 0;
        // Save current Mode into CSRs[mstatus].MPP.
        WriteCSR(state, MSTATUS, 11, 12, prev_mode);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movb 0x8148(%rax), %al
movb %al, -0x11(%rbp)
movq -0x8(%rbp), %rax
movq 0x8140(%rax), %rax
movq %rax, -0x20(%rbp)
movq $0x302, -0x28(%rbp)     # imm = 0x302
movq -0x20(%rbp), %rax
movq %rax, -0x40(%rbp)
movl $0x3f, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x40(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x13de
movq $0x303, -0x28(%rbp)     # imm = 0x303
movq -0x8(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x1, %eax
jg 0x1545
movq -0x8(%rbp), %rax
movq -0x28(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq -0x20(%rbp), %rcx
andq $0xffff, %rcx           # imm = 0xFFFF
shrq %cl, %rax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x1545
movq -0x8(%rbp), %rax
movb $0x1, 0x8148(%rax)
movq -0x10(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0xa10(%rax)
movq $0x0, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movl $0x105, %esi            # imm = 0x105
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x1600
cmpq $0x1, %rax
jne 0x1479
movq -0x20(%rbp), %rax
movq %rax, -0x48(%rbp)
movl $0x3f, %edi
callq 0x12b0
movq %rax, %rcx
movq -0x48(%rbp), %rax
andq %rcx, %rax
shlq $0x2, %rax
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq 0x830(%rax), %rcx
andq $-0x2, %rcx
addq -0x30(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0xa18(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0xa20(%rax)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x1, %ecx
movl %ecx, %edx
callq 0x1600
movq -0x50(%rbp), %rdi
movq %rax, %r8
movl $0x100, %esi            # imm = 0x100
movl $0x5, %ecx
movl %ecx, %edx
callq 0x1690
movq -0x8(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x1, %ecx
xorl %eax, %eax
movl %eax, %r8d
movl %ecx, %edx
callq 0x1690
movzbl -0x11(%rbp), %eax
cmpl $0x0, %eax
jne 0x1525
movq -0x8(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x8, %ecx
xorl %eax, %eax
movl %eax, %r8d
movl %ecx, %edx
callq 0x1690
jmp 0x1540
movq -0x8(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x8, %ecx
movl $0x1, %r8d
movl %ecx, %edx
callq 0x1690
jmp 0x15fa
movq -0x8(%rbp), %rax
movb $0x3, 0x8148(%rax)
movq -0x10(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x1a10(%rax)
movq $0x0, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movl $0x305, %esi            # imm = 0x305
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x1600
cmpq $0x1, %rax
jne 0x15a3
movq -0x20(%rbp), %rax
movq %rax, -0x58(%rbp)
movl $0x3f, %edi
callq 0x12b0
movq %rax, %rcx
movq -0x58(%rbp), %rax
andq %rcx, %rax
shlq $0x2, %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movq 0x1830(%rax), %rcx
andq $-0x2, %rcx
addq -0x38(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x1a18(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x1a20(%rax)
movq -0x8(%rbp), %rdi
movzbl -0x11(%rbp), %eax
movl %eax, %r8d
movl $0x300, %esi            # imm = 0x300
movl $0xb, %edx
movl $0xc, %ecx
callq 0x1690
addq $0x60, %rsp
popq %rbp
retq