aboutsummaryrefslogtreecommitdiffstats
path: root/src/irs.s
blob: 5cccb6e96f60fd1c50a7e81e195b8c35f6699377 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    .file "irs.s"
    .extern irs_table;
    .section .iwram, "ax", %progbits
    .arm
    .align
    .global irs_main

irs_main:
    @ Get the contents of IRQ_ENABLE, IRQ_ACK, and IRQ_CTRL
    ldr ip, mem_irq_base_reg        @ ip = (IRQ_ENABLE << 16) | IRQ_ACK
    ldr r0, [ip]                    @ r0 = irq_enable
    and r1, r0, r0, lsr #16         @ r1 = irq_enable & irq_ack

    @ Disable IRQ_CTRL for now.
    mov r3, #0                      @ r3 = 0
    strh r3, [ip, #8]               @ *(ip + 0x8) = r3

    @ r0 = irs_table address pointer
    @ r2 = tmp
    @ r3 = 0    (for r3; r3 < 14; r3++)
    ldr r0, = irs_table
irs_main_fp_search:
    @ Check that the current index is an active IRQ.
    mov r2, #1
    and r2, r1, r2, lsl r3
    cmp r2, #0
    beq irs_main_fp_search_not_enabled

    @ Extract the function pointer for this IRS if available.
    ldr r2, [r0]
    cmp r2, #0
    bne irs_main_handle_irs

irs_main_fp_search_not_enabled:
    add r0, r0, #4
    add r3, #1
    cmp r3, #14
    bne irs_main_fp_search
    b irs_main_exit

irs_main_handle_irs:
    @ r2: Contains IRQ function pointer.
    @ r3: Stores the IRQ index.

    @ Acknowledge that we are handling this interrupt writing to IRQ_ACK and
    @ IRQ_ACK_BIOS.
    mov r0, #1
    lsl r0, r0, r3
    strh r0, [ip, #2]
    ldr r1, mem_irq_ack_bios @ r1 = IRQ_ACK_BIOS
    str r0, [r1]

    @ Store the SPSR in one of the free registers and save it along with the
    @ return pointer.
    mrs r3, spsr
    stmfd   sp!, {r3, lr}

    @ Set CPU to system mode
    mrs     r3, cpsr
    bic     r3, r3, #0xDF
    orr     r3, r3, #0x1F
    msr     cpsr, r3

    @ Call isr function pointer
    stmfd   sp!, {lr}
    mov     lr, pc
    bx      r2
    ldmfd   sp!, {lr}

    @ Set CPU to irq mode
    mrs     r3, cpsr
    bic     r3, r3, #0xDF
    orr     r3, r3, #0x92
    msr     cpsr, r3

    @ Restore the SPSR and the registers.
    ldmfd   sp!, {r3, lr}
    msr     spsr, r3

irs_main_exit:
    @ Restore IRQ_CTRL.
    mov r3, #1                      @ r3 = 0
    strh r3, [ip, #8]               @ *(ip + 0x8) = r3
    bx lr

mem_irq_base_reg:
    .word 0x04000200 @ IRQ_ENABLE
mem_irq_ack_bios:
    .word 0x03007FF8 @ IRQ_ACK_BIOS