// File: /workspace/github_c_makefile_star2_O1/hobo0xcc[P]rve/src/cpu.c
// Function: HandleInterrupt
bool HandleInterrupt(State *state, uint64_t instr_addr) {
    uint16_t mint = 0;
    if (state->mode == MACHINE) {
        if (ReadCSR(state, MSTATUS, 3, 3) == 0) {
            return false;
        }

        mint = ReadCSR(state, MIP, 0, 15) & ReadCSR(state, MIE, 0, 15);
    } else if (state->mode == SUPERVISOR) {
        if (ReadCSR(state, SSTATUS, 1, 1) == 0) {
            return false;
        }

        mint = ReadCSR(state, SIP, 0, 15) & ReadCSR(state, SIE, 0, 15);
    } else if (state->mode == USER) {
        mint = ReadCSR(state, SIP, 0, 15) & ReadCSR(state, SIE, 0, 15);
    }
    if (mint == 0) {
        return false;
    }

    // uint16_t mint = ReadCSR(state, MIP, 0, 15) & ReadCSR(state, MIE, 0, 15);
    // printf("MIP: 0x%llx, MIE: 0x%llx\n", state->csr[MIP], state->csr[MIE]);
    uint64_t exception_code = 0;
    bool interrupted = true;
    if (mint & SetOneBit(11)) {
        exception_code = SetOneBit(63) | 11;
    } else if (mint & SetOneBit(9)) {
        exception_code = SetOneBit(63) | 9;
        // printf("Machine External Interrupt\n");
    } else if (mint & SetOneBit(7)) {
        exception_code = SetOneBit(63) | 7;
        // printf("mtimecmp: %llx, mtime: %llx\n", state->clint->mtimecmp, state->clint->mtime);
    } else if (mint & SetOneBit(5)) {
        exception_code = SetOneBit(63) | 5;
    } else if (mint & SetOneBit(3)) {
        exception_code = SetOneBit(63) | 3;
    } else if (mint & SetOneBit(1)) {
        exception_code = SetOneBit(63) | 1;
    } else {
        // There's no pending interrupt or the interrupt isn't implemented yet.
        interrupted = false;
    }

    if (interrupted) {
        state->excepted = true;
        state->exception_code = exception_code;
        HandleTrap(state, instr_addr);
        if (state->mode == MACHINE) {
            WriteCSR(state, MIP, exception_code & 0xffff, exception_code & 0xffff, 0);
        } else if (state->mode == SUPERVISOR) {
            WriteCSR(state, SIP, exception_code & 0xffff, exception_code & 0xffff, 0);
        } else if (state->mode == USER) {
            WriteCSR(state, SIP, exception_code & 0xffff, exception_code & 0xffff, 0);
        }
        return true;
    }

    return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movzbl 0x8148(%rdi), %edx
movl $0x828, %ecx            # imm = 0x828
movl $0xa28, %eax            # imm = 0xA28
testl %edx, %edx
je 0x1590
cmpl $0x1, %edx
je 0x1587
cmpl $0x3, %edx
jne 0x1598
testb $0x8, 0x1808(%rbx)
je 0x15d7
movl $0x1828, %ecx           # imm = 0x1828
movl $0x1a28, %eax           # imm = 0x1A28
jmp 0x1590
testb $0x2, 0x808(%rbx)
je 0x15d7
movl (%rbx,%rcx), %ecx
andl (%rbx,%rax), %ecx
jmp 0x159a
xorl %ecx, %ecx
testw %cx, %cx
je 0x15d7
movabsq $-0x7fffffffffffffff, %r15 # imm = 0x8000000000000001
movzwl %cx, %eax
btl $0xb, %eax
movb $0x1, %r14b
jb 0x15dc
btl $0x9, %eax
jb 0x15e2
testb %al, %al
js 0x15e8
testb $0x20, %al
jne 0x15ee
testb $0x8, %al
jne 0x15f4
andl $0x2, %eax
xorl %ecx, %ecx
shrl %eax
cmoveq %rcx, %r15
movl %eax, %r14d
jmp 0x15f8
xorl %r14d, %r14d
jmp 0x1646
orq $0xa, %r15
jmp 0x15f8
addq $0x8, %r15
jmp 0x15f8
addq $0x6, %r15
jmp 0x15f8
addq $0x4, %r15
jmp 0x15f8
addq $0x2, %r15
testb %r14b, %r14b
je 0x1646
movb $0x1, 0x8138(%rbx)
movq %r15, 0x8140(%rbx)
movq %rbx, %rdi
callq 0x1361
movzbl 0x8148(%rbx), %eax
testl %eax, %eax
je 0x1628
cmpl $0x3, %eax
je 0x162e
cmpl $0x1, %eax
jne 0x1646
movw $0x144, %ax             # imm = 0x144
jmp 0x1632
movw $0x344, %ax             # imm = 0x344
movzwl %ax, %esi
movzbl %r15b, %ecx
movq %rbx, %rdi
movl %ecx, %edx
xorl %r8d, %r8d
callq 0x14db
movl %r14d, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq