1 | /** |
---|
2 | * @file bsp_irq_asm.S |
---|
3 | * |
---|
4 | * Intererrupt handler for GameBoy Advance. |
---|
5 | */ |
---|
6 | /* |
---|
7 | * RTEMS GBA BSP |
---|
8 | * |
---|
9 | * Copyright (c) 2004 Markku Puro <markku.puro@kopteri.net> |
---|
10 | * |
---|
11 | * The license and distribution terms for this file may be |
---|
12 | * found in found in the file LICENSE in this distribution or at |
---|
13 | * http://www.rtems.com/license/LICENSE. |
---|
14 | * |
---|
15 | * $Id$ |
---|
16 | */ |
---|
17 | |
---|
18 | #define __asm__ |
---|
19 | #include <asm_macros.h> |
---|
20 | #include <gba_registers.h> |
---|
21 | #include <arm_mode_bits.h> |
---|
22 | /* @cond INCLUDE_ASM */ |
---|
23 | |
---|
24 | /** |
---|
25 | * Execute interrupt handler |
---|
26 | * function void ExecuteITHandler(void) |
---|
27 | * |
---|
28 | * Look at interrupt status register to determine source. |
---|
29 | * From source, determine offset into expanded vector table |
---|
30 | * and load handler address into r0. |
---|
31 | * irq_vector_table is defined in linkcmds |
---|
32 | * |
---|
33 | */ |
---|
34 | .align |
---|
35 | /* .section .iwram */ |
---|
36 | |
---|
37 | PUBLIC_ARM_FUNCTION(ExecuteITHandler) |
---|
38 | ldr r1, =GBA_REG_IE_ADDR |
---|
39 | ldrh r1, [r1] |
---|
40 | ldr r2, =GBA_REG_IF_ADDR |
---|
41 | ldrh r2, [r2] |
---|
42 | and r3, r1, r2 /* only look at interrupts which are enabled */ |
---|
43 | |
---|
44 | check_lcdv: |
---|
45 | tst r3, #0x0001 |
---|
46 | beq check_lcdh |
---|
47 | ldr r0, =(irq_vector_table + (4 * 0)) /* load the vector number */ |
---|
48 | ldr r3,=0x0001 |
---|
49 | b get_handler |
---|
50 | |
---|
51 | check_lcdh: |
---|
52 | tst r3, #0x0002 |
---|
53 | beq check_lcdvc |
---|
54 | ldr r0, =(irq_vector_table + (4 * 1)) /* load the vector number */ |
---|
55 | ldr r3,=0x0002 |
---|
56 | b get_handler |
---|
57 | |
---|
58 | check_lcdvc: |
---|
59 | tst r3, #0x0004 |
---|
60 | beq check_t0 |
---|
61 | ldr r0, =(irq_vector_table + (4 * 2)) /* load the vector number */ |
---|
62 | ldr r3,=0x0004 |
---|
63 | b get_handler |
---|
64 | |
---|
65 | check_t0: |
---|
66 | tst r3, #0x0008 |
---|
67 | beq check_t1 |
---|
68 | ldr r0, =(irq_vector_table + (4 * 3)) /* load the vector number */ |
---|
69 | ldr r3,=0x0008 |
---|
70 | b get_handler |
---|
71 | |
---|
72 | check_t1: |
---|
73 | tst r3, #0x0010 |
---|
74 | beq check_t2 |
---|
75 | ldr r0, =(irq_vector_table + (4 * 4)) /* load the vector number */ |
---|
76 | ldr r3,=0x0010 |
---|
77 | b get_handler |
---|
78 | |
---|
79 | check_t2: |
---|
80 | tst r3, #0x0020 |
---|
81 | beq check_t3 |
---|
82 | ldr r0, =(irq_vector_table + (4 * 5)) /* load the vector number */ |
---|
83 | ldr r3,=0x0020 |
---|
84 | b get_handler |
---|
85 | |
---|
86 | check_t3: |
---|
87 | tst r3, #0x0040 |
---|
88 | beq check_ser |
---|
89 | ldr r0, =(irq_vector_table + (4 * 6)) /* load the vector number */ |
---|
90 | ldr r3,=0x0040 |
---|
91 | b get_handler |
---|
92 | |
---|
93 | check_ser: |
---|
94 | tst r3, #0x0080 |
---|
95 | beq check_dma0 |
---|
96 | ldr r0, =(irq_vector_table + (4 * 7)) /* load the vector number */ |
---|
97 | ldr r3,=0x0080 |
---|
98 | b get_handler |
---|
99 | |
---|
100 | check_dma0: |
---|
101 | tst r3, #0x0100 |
---|
102 | beq check_dma1 |
---|
103 | ldr r0, =(irq_vector_table + (4 * 8)) /* load the vector number */ |
---|
104 | ldr r3,=0x0100 |
---|
105 | b get_handler |
---|
106 | |
---|
107 | check_dma1: |
---|
108 | tst r3, #0x0200 |
---|
109 | beq check_dma2 |
---|
110 | ldr r0, =(irq_vector_table + (4 * 9)) /* load the vector number */ |
---|
111 | ldr r3,=0x0200 |
---|
112 | b get_handler |
---|
113 | |
---|
114 | check_dma2: |
---|
115 | tst r3, #0x0400 |
---|
116 | beq check_dma3 |
---|
117 | ldr r0, =(irq_vector_table + (4 * 10)) /* load the vector number */ |
---|
118 | ldr r3,=0x0400 |
---|
119 | b get_handler |
---|
120 | |
---|
121 | check_dma3: |
---|
122 | tst r3, #0x0800 |
---|
123 | beq check_keypad |
---|
124 | ldr r0, =(irq_vector_table + (4 * 11)) /* load the vector number */ |
---|
125 | ldr r3,=0x0800 |
---|
126 | b get_handler |
---|
127 | |
---|
128 | check_keypad: |
---|
129 | tst r3, #0x1000 |
---|
130 | beq check_gamepak |
---|
131 | ldr r0, =(irq_vector_table + (4 * 12)) /* load the vector number */ |
---|
132 | ldr r3,=0x1000 |
---|
133 | b get_handler |
---|
134 | |
---|
135 | check_gamepak: |
---|
136 | tst r3, #0x2000 |
---|
137 | beq IRQ_NoInterrupt |
---|
138 | ldr r0, =(irq_vector_table + (4 * 13)) /* load the vector number */ |
---|
139 | ldr r3,=0x2000 |
---|
140 | b get_handler |
---|
141 | |
---|
142 | unknown_irq: |
---|
143 | ldr r0, =(default_int_handler) /* Unknown Interrupt? */ |
---|
144 | ldr r3,=0x0000 |
---|
145 | |
---|
146 | get_handler: |
---|
147 | ldr r0, [r0] /* extract the IT handler */ |
---|
148 | |
---|
149 | ldr r2, =GBA_REG_IF_ADDR /* Clear IF */ |
---|
150 | strh r3, [r2] |
---|
151 | |
---|
152 | /* |
---|
153 | * re-enable interrupts at processor level |
---|
154 | */ |
---|
155 | mrs r1, cpsr |
---|
156 | bic r1, r1, #Int_Bits |
---|
157 | msr cpsr, r1 |
---|
158 | |
---|
159 | stmdb sp!,{lr} |
---|
160 | ldr lr, =IRQ_return /* prepare the return from handler */ |
---|
161 | mov pc, r0 /* EXECUTE INT HANDLER */ |
---|
162 | |
---|
163 | IRQ_return: |
---|
164 | ldmia sp!,{lr} |
---|
165 | |
---|
166 | /* |
---|
167 | * disable interrupts_again |
---|
168 | */ |
---|
169 | mrs r0, cpsr |
---|
170 | orr r0, r0, #Int_Bits |
---|
171 | msr cpsr, r0 |
---|
172 | |
---|
173 | IRQ_NoInterrupt: |
---|
174 | /* return to the "main" interrupt handler */ |
---|
175 | mov pc, lr |
---|
176 | |
---|
177 | LABEL_END(ExecuteITHandler) |
---|
178 | /* @endcond */ |
---|
179 | |
---|