// File: /workspace/github_c_makefile_star2_O0/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
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movw $0x0, -0x1a(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x3, %eax
jne 0x17de
movq -0x10(%rbp), %rdi
movl $0x300, %esi            # imm = 0x300
movl $0x3, %ecx
movl %ecx, %edx
callq 0x1600
cmpq $0x0, %rax
jne 0x179d
movb $0x0, -0x1(%rbp)
jmp 0x1b1c
movq -0x10(%rbp), %rdi
movl $0x344, %esi            # imm = 0x344
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rdi
movl $0x304, %esi            # imm = 0x304
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, %rcx
movq -0x38(%rbp), %rax
andq %rcx, %rax
movw %ax, -0x1a(%rbp)
jmp 0x18a0
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x1, %eax
jne 0x1850
movq -0x10(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0x1, %ecx
movl %ecx, %edx
callq 0x1600
cmpq $0x0, %rax
jne 0x1812
movb $0x0, -0x1(%rbp)
jmp 0x1b1c
movq -0x10(%rbp), %rdi
movl $0x144, %esi            # imm = 0x144
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movl $0x104, %esi            # imm = 0x104
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, %rcx
movq -0x40(%rbp), %rax
andq %rcx, %rax
movw %ax, -0x1a(%rbp)
jmp 0x189e
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x0, %eax
jne 0x189c
movq -0x10(%rbp), %rdi
movl $0x144, %esi            # imm = 0x144
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movl $0x104, %esi            # imm = 0x104
xorl %edx, %edx
movl $0xf, %ecx
callq 0x1600
movq %rax, %rcx
movq -0x48(%rbp), %rax
andq %rcx, %rax
movw %ax, -0x1a(%rbp)
jmp 0x189e
jmp 0x18a0
movzwl -0x1a(%rbp), %eax
cmpl $0x0, %eax
jne 0x18b2
movb $0x0, -0x1(%rbp)
jmp 0x1b1c
movq $0x0, -0x28(%rbp)
movb $0x1, -0x29(%rbp)
movzwl -0x1a(%rbp), %eax
movq %rax, -0x50(%rbp)
movl $0xb, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x50(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x18f7
movl $0x3f, %edi
callq 0x12f0
orq $0xb, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a19
movzwl -0x1a(%rbp), %eax
movq %rax, -0x58(%rbp)
movl $0x9, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x58(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x1930
movl $0x3f, %edi
callq 0x12f0
orq $0x9, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a17
movzwl -0x1a(%rbp), %eax
movq %rax, -0x60(%rbp)
movl $0x7, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x60(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x1969
movl $0x3f, %edi
callq 0x12f0
orq $0x7, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a15
movzwl -0x1a(%rbp), %eax
movq %rax, -0x68(%rbp)
movl $0x5, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x68(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x199f
movl $0x3f, %edi
callq 0x12f0
orq $0x5, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a13
movzwl -0x1a(%rbp), %eax
movq %rax, -0x70(%rbp)
movl $0x3, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x70(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x19d5
movl $0x3f, %edi
callq 0x12f0
orq $0x3, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a11
movzwl -0x1a(%rbp), %eax
movq %rax, -0x78(%rbp)
movl $0x1, %edi
callq 0x12f0
movq %rax, %rcx
movq -0x78(%rbp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x1a0b
movl $0x3f, %edi
callq 0x12f0
orq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x1a0f
movb $0x0, -0x29(%rbp)
jmp 0x1a11
jmp 0x1a13
jmp 0x1a15
jmp 0x1a17
jmp 0x1a19
testb $0x1, -0x29(%rbp)
je 0x1b18
movq -0x10(%rbp), %rax
movb $0x1, 0x8138(%rax)
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8140(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x1380
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x3, %eax
jne 0x1a8e
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movb %al, %cl
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movl $0x344, %esi            # imm = 0x344
xorl %edx, %edx
movl %edx, %r8d
movzbl %cl, %edx
movzbl %al, %ecx
callq 0x1690
jmp 0x1b12
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x1, %eax
jne 0x1acf
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movb %al, %cl
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movl $0x144, %esi            # imm = 0x144
xorl %edx, %edx
movl %edx, %r8d
movzbl %cl, %edx
movzbl %al, %ecx
callq 0x1690
jmp 0x1b10
movq -0x10(%rbp), %rax
movzbl 0x8148(%rax), %eax
cmpl $0x0, %eax
jne 0x1b0e
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movb %al, %cl
movq -0x28(%rbp), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movl $0x144, %esi            # imm = 0x144
xorl %edx, %edx
movl %edx, %r8d
movzbl %cl, %edx
movzbl %al, %ecx
callq 0x1690
jmp 0x1b10
jmp 0x1b12
movb $0x1, -0x1(%rbp)
jmp 0x1b1c
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x80, %rsp
popq %rbp
retq
nopw (%rax,%rax)