// File: /workspace/github_c_makefile_star2_O0/juliuswwj[P]emch55x/core.c
// Function: handle_interrupts
void handle_interrupts(struct em8051 *aCPU)
{
    int dest_ip = -1;
    int hi = 0;
    int lo = 0;

    // can't interrupt high level
    if (aCPU->mInterruptActive > 1) 
        return;    

    if (aCPU->mSFR[REG_IE] & IEMASK_EA)
    {
        // Interrupts enabled
        if (aCPU->mSFR[REG_IE] & IEMASK_EX0 && aCPU->mSFR[REG_TCON] & TCONMASK_IE0)
        {
            // External int 0 
            dest_ip = 0x3;
            if (aCPU->mSFR[REG_IP] & IPMASK_PX0)
                hi = 1;
            lo = 1;
        }
        if (aCPU->mSFR[REG_IE] & IEMASK_ET0 && aCPU->mSFR[REG_TCON] & TCONMASK_TF0 && !hi)
        {
            // Timer/counter 0 
            if (!lo)
            {
                dest_ip = 0xb;
                lo = 1;
            }
            if (aCPU->mSFR[REG_IP] & IPMASK_PT0)
            {
                hi = 1;
                dest_ip = 0xb;
            }
        }
        if (aCPU->mSFR[REG_IE] & IEMASK_EX1 && aCPU->mSFR[REG_TCON] & TCONMASK_IE1 && !hi)
        {
            // External int 1 
            if (!lo)
            {
                dest_ip = 0x13;
                lo = 1;
            }
            if (aCPU->mSFR[REG_IP] & IPMASK_PX1)
            {
                hi = 1;
                dest_ip = 0x13;
            }
        }
        if (aCPU->mSFR[REG_IE] & IEMASK_ET1 && aCPU->mSFR[REG_TCON] & TCONMASK_TF1 && !hi)
        {
            // Timer/counter 1 enabled
            if (!lo)
            {
                dest_ip = 0x1b;
                lo = 1;
            }
            if (aCPU->mSFR[REG_IP] & IPMASK_PT1)
            {
                hi = 1;
                dest_ip = 0x1b;
            }
        }
        if (aCPU->mSFR[REG_IE] & IEMASK_ES && !hi)
        {
            // Serial port interrupt 
            if (!lo)
            {
                dest_ip = 0x23;
                lo = 1;
            }
            if (aCPU->mSFR[REG_IP] & IPMASK_PS)
            {
                hi = 1;
                dest_ip = 0x23;
            }
            // TODO
        }
        if (aCPU->mSFR[REG_IE] & IEMASK_ET2 && !hi)
        {
            // Timer 2 (8052 only)
            if (!lo)
            {
                dest_ip = 0x2b; // guessed
                lo = 1;
            }
            if (aCPU->mSFR[REG_IP] & IPMASK_PT2)
            {
                hi = 1;
                dest_ip = 0x2b; // guessed
            }
            // TODO
        }
    }
    
    // no interrupt
    if (dest_ip == -1)
        return;

    // can't interrupt same-level
    if (aCPU->mInterruptActive == 1 && !hi)
        return; 

    // some interrupt occurs; perform LCALL
    push_to_stack(aCPU, aCPU->mPC & 0xff);
    push_to_stack(aCPU, aCPU->mPC >> 8);
    aCPU->mPC = dest_ip;
    // wait for 2 ticks instead of one since we were not executing
    // this LCALL before.
    aCPU->mTickDelay = 2;
    switch (dest_ip)
    {
    case 0xb:
        aCPU->mSFR[REG_TCON] &= ~TCONMASK_TF0; // clear overflow flag
        break;
    case 0x1b:
        aCPU->mSFR[REG_TCON] &= ~TCONMASK_TF1; // clear overflow flag
        break;
    }

    if (hi)
    {
        aCPU->mInterruptActive |= 2;
    }
    else
    {
        aCPU->mInterruptActive = 1;
    }
    aCPU->int_a[hi] = aCPU->mSFR[REG_ACC];
    aCPU->int_psw[hi] = aCPU->mSFR[REG_PSW];
    aCPU->int_sp[hi] = aCPU->mSFR[REG_SP];
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movl $0xffffffff, -0xc(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x1, 0x1068(%rax)
jle 0x65c3
jmp 0x6916
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x6808
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x662e
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x662e
movl $0x3, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x6627
movl $0x1, -0x10(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6694
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x6694
cmpl $0x0, -0x10(%rbp)
jne 0x6694
cmpl $0x0, -0x14(%rbp)
jne 0x6670
movl $0xb, -0xc(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6692
movl $0x1, -0x10(%rbp)
movl $0xb, -0xc(%rbp)
jmp 0x6694
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x66fa
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x66fa
cmpl $0x0, -0x10(%rbp)
jne 0x66fa
cmpl $0x0, -0x14(%rbp)
jne 0x66d6
movl $0x13, -0xc(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x66f8
movl $0x1, -0x10(%rbp)
movl $0x13, -0xc(%rbp)
jmp 0x66fa
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x6762
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x6762
cmpl $0x0, -0x10(%rbp)
jne 0x6762
cmpl $0x0, -0x14(%rbp)
jne 0x673e
movl $0x1b, -0xc(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x6760
movl $0x1, -0x10(%rbp)
movl $0x1b, -0xc(%rbp)
jmp 0x6762
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x67b4
cmpl $0x0, -0x10(%rbp)
jne 0x67b4
cmpl $0x0, -0x14(%rbp)
jne 0x6790
movl $0x23, -0xc(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x67b2
movl $0x1, -0x10(%rbp)
movl $0x23, -0xc(%rbp)
jmp 0x67b4
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x28(%rax), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x6806
cmpl $0x0, -0x10(%rbp)
jne 0x6806
cmpl $0x0, -0x14(%rbp)
jne 0x67e2
movl $0x2b, -0xc(%rbp)
movl $0x1, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x38(%rax), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x6804
movl $0x1, -0x10(%rbp)
movl $0x2b, -0xc(%rbp)
jmp 0x6806
jmp 0x6808
cmpl $-0x1, -0xc(%rbp)
jne 0x6813
jmp 0x6916
movq -0x8(%rbp), %rax
cmpl $0x1, 0x1068(%rax)
jne 0x682b
cmpl $0x0, -0x10(%rbp)
jne 0x682b
jmp 0x6916
movq -0x8(%rbp), %rdi
movzbl 0x38(%rdi), %esi
callq 0xaef0
movq -0x8(%rbp), %rdi
movl 0x38(%rdi), %esi
sarl $0x8, %esi
callq 0xaef0
movl -0xc(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x38(%rax)
movq -0x8(%rbp), %rax
movl $0x2, 0x3c(%rax)
movl -0xc(%rbp), %eax
movl %eax, -0x18(%rbp)
subl $0xb, %eax
je 0x6873
jmp 0x6869
movl -0x18(%rbp), %eax
subl $0x1b, %eax
je 0x6887
jmp 0x689c
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %ecx
andl $-0x21, %ecx
movb %cl, 0x8(%rax)
jmp 0x689c
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x8(%rax), %ecx
andl $0xffffff7f, %ecx       # imm = 0xFFFFFF7F
movb %cl, 0x8(%rax)
cmpl $0x0, -0x10(%rbp)
je 0x68b7
movq -0x8(%rbp), %rax
movl 0x1068(%rax), %ecx
orl $0x2, %ecx
movl %ecx, 0x1068(%rax)
jmp 0x68c5
movq -0x8(%rbp), %rax
movl $0x1, 0x1068(%rax)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x60(%rax), %edx
movq -0x8(%rbp), %rax
movslq -0x10(%rbp), %rcx
movl %edx, 0x106c(%rax,%rcx,4)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x50(%rax), %edx
movq -0x8(%rbp), %rax
movslq -0x10(%rbp), %rcx
movl %edx, 0x1074(%rax,%rcx,4)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movzbl 0x1(%rax), %edx
movq -0x8(%rbp), %rax
movslq -0x10(%rbp), %rcx
movl %edx, 0x107c(%rax,%rcx,4)
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)