1: /*
2: *----------------------------------------------------------------------
3: * T-Kernel 2.0 Software Package
4: *
5: * Copyright 2011 by Ken Sakamura.
6: * This software is distributed under the latest version of T-License 2.x.
7: *----------------------------------------------------------------------
8: *
9: * Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
10: * Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
11: *
12: *----------------------------------------------------------------------
13: */
14:
15: /*
16: * eitentry.S
17: *
18: * EM1D512 (ARM1176JZF-S) exception branch handling
19: */
20:
21: #define _in_asm_source_
22:
23: #include <machine.h>
24: #include <tk/sysdef.h>
25: #include <arm/em1d512.h>
26: #include <sys/sysinfo.h>
27:
28: #define base(n) ( (n) & 0xfffff000 )
29: #define offs(n) ( (n) & 0x00000fff )
30:
31: // see <sys/sysdepend/tef_em1d/sysinfo_depend.h>
32: #define N_INTVEC 256
33:
34: /*
35: * EIT entry
36: */
37:
38: .section EITBRA, "ax"
39: .arm
40: .org 0x00000000
41: b startup_entry // 00 : reset
42: b undef_entry // 04 : undefined instruction exception
43: b svc_entry // 08 : supervisor call (SVC)
44: b iabort_entry // 0C : prefetch abort
45: b dabort_entry // 10 : data abort
46: nop // 14 : (reserved)
47: b irq_entry // 18 : interrupt
48: .org 0x0000001c // 1C : fast interrupt
49:
50: /*
51: * fast interrupt
52: * calls the handler defined at FIQ interrupt vector unconditionally.
53: * no saving of registers to stack is performed.
54: * the content of R12_fiq(ip) register is overwritten.
55: */
56: fiq_entry:
57: ldr ip, =base(EIT_VECTBL)
58: ldr ip, [ip, #offs(EITVEC(EIT_FIQ))]
59: bx ip
60:
61: /*
62: * interrupt
63: * ACPU interrupt mask status register of Interrupt controller (AINT)
64: * Judge the priority of interrupts using (IT0_MST0,1,2),
65: * the highest interrupt's handler is called by jumping into it.
66: * Interrupt priority is descending order of interrupt factor (INT 0-95) , and INT 95 (IRQ 95) is highest.
67: * INT 0 (IRQ 0) has the lowest priority.
68: * If there is no cause of the interrupt, the handler of INT 95 (IRQ95) is called.
69: * +---------------+
70: * sp -> |R3 |
71: * |R12=ip |
72: * |R14=lr | <- return address from interrupt
73: * |SPSR |
74: * +---------------+
75: * registers upon handler invocation
76: * ip = vector table address
77: * lr = indeterminate
78: */
79: irq_entry:
80: sub lr, lr, #4 // return address adjustment
81: srsdb sp!, #PSR_IRQ // save registers
82: stmfd sp!, {r3, ip}
83:
84: ldr lr, =base(AINTBase)
85: ldr ip, =EITVEC(EIT_IRQ(95))
86:
87: ldr r3, [lr, #offs(IT0_MST2)]
88: cmp r3, #0
89: bne l_irq_br
90:
91: sub ip, ip, #32*4
92: ldr r3, [lr, #offs(IT0_MST1)]
93: cmp r3, #0
94: bne l_irq_br
95:
96: sub ip, ip, #32*4
97: ldr r3, [lr, #offs(IT0_MST0)]
98: cmp r3, #0
99: bne l_irq_br
100:
101: ldr ip, =EITVEC(EIT_IRQ(95))
102:
103: l_irq_br:
104: clzne r3, r3
105: ldr lr, [ip, -r3, lsl #2]!
106: cmp lr, #0
107: bxne lr
108: b default_entry
109:
110: /*
111: * GPIO interrupt
112: * Interrupt obtained by means of input port interrupt maskable status register (GIO_MST)
113: * is analyzed to check the interrupt priority, and if appropriate, the highest priority interrupt handler is entered.
114: * branch and call handler.
115: * interrupt priority is descending order of input port NUMBER (port 0 - port 127). port 127 has the highest priority, and
116: * port 0 has the lowest priority GPIO interrupts are grouped : each group has 16 interrupts, and
117: * their priorities are considered only within the context of each group.
118: * if there is no cause of interupt, the handler of IRQ95 is called.
119: * +---------------+
120: * sp -> |R3 |
121: * |R12=ip |
122: * |R14=lr | <- return address from interrupt
123: * |SPSR |
124: * +---------------+
125: * registers upon handler invocation
126: * ip = vector table address
127: * lr = indeterminate
128: */
129: .macro gio_e reg, vec
130: ldr lr, =base(\reg)
131: ldr r3, [lr, #offs(\reg)]
132: lsls r3, r3, #16
133: beq l_gio_spurious
134:
135: ldr ip, =\vec
136: clz r3, r3
137: ldr lr, [ip, -r3, lsl #2]!
138: cmp lr, #0
139: bxne lr
140: b default_entry
141: .endm
142: .macro gio_o reg, vec
143: ldr lr, =base(\reg)
144: ldr r3, [lr, #offs(\reg)]
145: lsrs ip, r3, #16
146: beq l_gio_spurious
147:
148: ldr ip, =\vec
149: clz r3, r3
150: ldr lr, [ip, -r3, lsl #2]!
151: cmp lr, #0
152: bxne lr
153: b default_entry
154: .endm
155:
156: .globl Csym(_gio0Hdr)
157: .type Csym(_gio0Hdr), %function
158: .globl Csym(_gio1Hdr)
159: .type Csym(_gio1Hdr), %function
160: .globl Csym(_gio2Hdr)
161: .type Csym(_gio2Hdr), %function
162: .globl Csym(_gio3Hdr)
163: .type Csym(_gio3Hdr), %function
164: .globl Csym(_gio4Hdr)
165: .type Csym(_gio4Hdr), %function
166: .globl Csym(_gio5Hdr)
167: .type Csym(_gio5Hdr), %function
168: .globl Csym(_gio6Hdr)
169: .type Csym(_gio6Hdr), %function
170: .globl Csym(_gio7Hdr)
171: .type Csym(_gio7Hdr), %function
172: Csym(_gio0Hdr): gio_e GIO_MST(GIO_L), EITVEC(EIT_GPIO( 15))
173: Csym(_gio1Hdr): gio_o GIO_MST(GIO_L), EITVEC(EIT_GPIO( 31))
174: Csym(_gio2Hdr): gio_e GIO_MST(GIO_H), EITVEC(EIT_GPIO( 47))
175: Csym(_gio3Hdr): gio_o GIO_MST(GIO_H), EITVEC(EIT_GPIO( 63))
176: Csym(_gio4Hdr): gio_e GIO_MST(GIO_HH), EITVEC(EIT_GPIO( 79))
177: Csym(_gio5Hdr): gio_o GIO_MST(GIO_HH), EITVEC(EIT_GPIO( 95))
178: Csym(_gio6Hdr): gio_e GIO_MST(GIO_HHH), EITVEC(EIT_GPIO(111))
179: Csym(_gio7Hdr): gio_o GIO_MST(GIO_HHH), EITVEC(EIT_GPIO(127))
180:
181: l_gio_spurious:
182: ldr ip, =base(EITVEC(EIT_IRQ(95)))
183: ldr lr, [ip, #offs(EITVEC(EIT_IRQ(95)))]!
184: cmp lr, #0
185: bxne lr
186: b default_entry
187:
188: /*
189: * undefined instruction
190: * +---------------+
191: * sp -> |R12=ip |
192: * |R14=lr | <- the return address, i.e., the next address that follows the undefined instruction
193: * |SPSR |
194: * +---------------+
195: * registers upon handler invocation
196: * ip = vector table address
197: * lr = indeterminate
198: */
199: undef_entry:
200: srsdb sp!, #PSR_UND // save registers
201: stmfd sp!, {ip}
202:
203: ldr ip, =base(EITVEC(EIT_UNDEF))
204: ldr lr, [ip, #offs(EITVEC(EIT_UNDEF))]!
205: cmp lr, #0
206: bxne lr
207: b default_entry
208:
209: /*
210: * supervisor call(SVC)
211: * the valid range of supervisor call number is 0-255 (N_INTVEC - 1).
212: * if an out of range value is given, treat it as SVC 0, and invokes the default handler.
213: * +---------------+
214: * sp -> |R12=ip |
215: * |R14=lr | <- return address: the address that follows the SVC instruction
216: * |SPSR |
217: * +---------------+
218: * registers upon handler invocation
219: * ip = vector table address
220: * lr = indeterminate
221: */
222: svc_entry:
223: srsdb sp!, #PSR_SVC // save registers
224: stmfd sp!, {ip}
225:
226: mrs ip, spsr
227: tst ip, #PSR_T
228: ldrneh ip, [lr, #-2] // Thumb instruction
229: ldreq ip, [lr, #-4] // ARM instruction
230: bicne lr, ip, #0xff00
231: biceq lr, ip, #0xff000000
232: cmp lr, #N_INTVEC // lr = software interrupt number
233: movge lr, #0
234:
235: ldr ip, =EIT_VECTBL
236: ldr lr, [ip, lr, lsl #2]!
237: cmp lr, #0
238: bxne lr
239: b default_entry
240:
241: /*
242: * prefetch abort
243: * in the case of debug event, debug abort (instruction) handler is called.
244: * Otherwise, prefetch abort handler is called.
245: * +---------------+
246: * sp -> |R12=ip |
247: * |R14=lr | <- return address: the address of aborted instruction
248: * |SPSR |
249: * +---------------+
250: * registers upon handler invocation
251: * ip = vector table address
252: * lr = indeterminate
253: */
254: iabort_entry:
255: sub lr, lr, #4 // return address adjustment
256: srsdb sp!, #PSR_ABT // save registers
257: stmfd sp!, {ip}
258:
259: mrc p15, 0, ip, c5, c0, 1 // IFSR
260: tst ip, #0x400 // FS[4]
261: and ip, ip, #0x00f // FS[3:0]
262: cmpeq ip, #FSR_DebugEvent
263:
264: ldr ip, =base(EITVEC(EIT_IABORT))
265: ldrne lr, [ip, #offs(EITVEC(EIT_IABORT))]!
266: ldreq lr, [ip, #offs(EITVEC(EIT_IDEBUG))]!
267: cmp lr, #0
268: bxne lr
269: b default_entry
270:
271: /*
272: * data abort
273: * in the case of debug event, debug abort (data) handler is called.
274: * Otherwise, data abort handler is called.
275: * +---------------+
276: * sp -> |R12=ip |
277: * |R14=lr | <- return address: the address of aborted instruction
278: * |SPSR |
279: * +---------------+
280: * registers upon handler invocation
281: * ip = vector table address
282: * lr = indeterminate
283: */
284: dabort_entry:
285: sub lr, lr, #8 // return address adjustment
286: srsdb sp!, #PSR_ABT // save registers
287: stmfd sp!, {ip}
288:
289: mrc p15, 0, ip, c5, c0, 0 // DFSR
290: tst ip, #0x400 // FS[4]
291: and ip, ip, #0x00f // FS[3:0]
292: cmpeq ip, #FSR_DebugEvent
293:
294: ldr ip, =base(EITVEC(EIT_DABORT))
295: ldrne lr, [ip, #offs(EITVEC(EIT_DABORT))]!
296: ldreq lr, [ip, #offs(EITVEC(EIT_DDEBUG))]!
297: cmp lr, #0
298: bxne lr
299: b default_entry
300:
301: /*
302: * default handler
303: * stack contains the details of the generated exception.
304: * registers upon handler invocation
305: * ip = address of the vector table for the raised exception
306: * lr = indeterminate
307: */
308: default_entry:
309: ldr lr, =base(EITVEC(EIT_DEFAULT))
310: ldr lr, [lr, #offs(EITVEC(EIT_DEFAULT))]
311: bx lr
312:
313: .pool