blob: 493f3373f3cd7ed61ff0df45fba8e77ed71e7a54 [file] [log] [blame]
Albert ARIBAUD9852cc62014-04-15 16:13:51 +02001/*
2 * vectors - Generic ARM exception table code
3 *
4 * Copyright (c) 1998 Dan Malek <dmalek@jlc.net>
5 * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6 * Copyright (c) 2000 Wolfgang Denk <wd@denx.de>
7 * Copyright (c) 2001 Alex Züpke <azu@sysgo.de>
8 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
9 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
11 * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net>
12 *
13 * SPDX-License-Identifier: GPL-2.0+
14 */
15
Christian Riesch80c5a532014-07-07 11:07:25 +020016#include <config.h>
17
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020018/*
19 *************************************************************************
20 *
21 * Symbol _start is referenced elsewhere, so make it global
22 *
23 *************************************************************************
24 */
25
26.globl _start
27
28/*
29 *************************************************************************
30 *
31 * Vectors have their own section so linker script can map them easily
32 *
33 *************************************************************************
34 */
35
36 .section ".vectors", "x"
37
38/*
39 *************************************************************************
40 *
41 * Exception vectors as described in ARM reference manuals
42 *
43 * Uses indirect branch to allow reaching handlers anywhere in memory.
44 *
45 *************************************************************************
46 */
47
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020048#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
49 .word CONFIG_SYS_DV_NOR_BOOT_CFG
50#endif
51
52_start:
53 ldr pc, _reset
54 ldr pc, _undefined_instruction
55 ldr pc, _software_interrupt
56 ldr pc, _prefetch_abort
57 ldr pc, _data_abort
58 ldr pc, _not_used
59 ldr pc, _irq
60 ldr pc, _fiq
61
62/*
63 *************************************************************************
64 *
65 * Indirect vectors table
66 *
67 * Symbols referenced here must be defined somewhere else
68 *
69 *************************************************************************
70 */
71
72 .globl _undefined_instruction
73 .globl _software_interrupt
74 .globl _prefetch_abort
75 .globl _data_abort
76 .globl _not_used
77 .globl _irq
78 .globl _fiq
79
80_reset: .word reset
81_undefined_instruction: .word undefined_instruction
82_software_interrupt: .word software_interrupt
83_prefetch_abort: .word prefetch_abort
84_data_abort: .word data_abort
85_not_used: .word not_used
86_irq: .word irq
87_fiq: .word fiq
88
89 .balignl 16,0xdeadbeef
90
91/*
92 *************************************************************************
93 *
94 * Interrupt handling
95 *
96 *************************************************************************
97 */
98
99/* SPL interrupt handling: just hang */
100
101#ifdef CONFIG_SPL_BUILD
102
103 .align 5
104undefined_instruction:
105software_interrupt:
106prefetch_abort:
107data_abort:
108not_used:
109irq:
110fiq:
111
1121:
113 bl 1b /* hang and never return */
114
115#else /* !CONFIG_SPL_BUILD */
116
117/* IRQ stack memory (calculated at run-time) + 8 bytes */
118.globl IRQ_STACK_START_IN
119IRQ_STACK_START_IN:
120 .word 0x0badc0de
121
122#ifdef CONFIG_USE_IRQ
123/* IRQ stack memory (calculated at run-time) */
124.globl IRQ_STACK_START
125IRQ_STACK_START:
126 .word 0x0badc0de
127
128/* IRQ stack memory (calculated at run-time) */
129.globl FIQ_STACK_START
130FIQ_STACK_START:
131 .word 0x0badc0de
132
133#endif /* CONFIG_USE_IRQ */
134
135@
136@ IRQ stack frame.
137@
138#define S_FRAME_SIZE 72
139
140#define S_OLD_R0 68
141#define S_PSR 64
142#define S_PC 60
143#define S_LR 56
144#define S_SP 52
145
146#define S_IP 48
147#define S_FP 44
148#define S_R10 40
149#define S_R9 36
150#define S_R8 32
151#define S_R7 28
152#define S_R6 24
153#define S_R5 20
154#define S_R4 16
155#define S_R3 12
156#define S_R2 8
157#define S_R1 4
158#define S_R0 0
159
160#define MODE_SVC 0x13
161#define I_BIT 0x80
162
163/*
164 * use bad_save_user_regs for abort/prefetch/undef/swi ...
165 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
166 */
167
168 .macro bad_save_user_regs
169 @ carve out a frame on current user stack
170 sub sp, sp, #S_FRAME_SIZE
171 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
172 ldr r2, IRQ_STACK_START_IN
173 @ get values for "aborted" pc and cpsr (into parm regs)
174 ldmia r2, {r2 - r3}
175 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
176 add r5, sp, #S_SP
177 mov r1, lr
178 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
179 mov r0, sp @ save current stack into r0 (param register)
180 .endm
181
182 .macro irq_save_user_regs
183 sub sp, sp, #S_FRAME_SIZE
184 stmia sp, {r0 - r12} @ Calling r0-r12
185 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
186 add r8, sp, #S_PC
187 stmdb r8, {sp, lr}^ @ Calling SP, LR
188 str lr, [r8, #0] @ Save calling PC
189 mrs r6, spsr
190 str r6, [r8, #4] @ Save CPSR
191 str r0, [r8, #8] @ Save OLD_R0
192 mov r0, sp
193 .endm
194
195 .macro irq_restore_user_regs
196 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
197 mov r0, r0
198 ldr lr, [sp, #S_PC] @ Get PC
199 add sp, sp, #S_FRAME_SIZE
200 subs pc, lr, #4 @ return & move spsr_svc into cpsr
201 .endm
202
203 .macro get_bad_stack
204 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
205
206 str lr, [r13] @ save caller lr in position 0 of saved stack
207 mrs lr, spsr @ get the spsr
208 str lr, [r13, #4] @ save spsr in position 1 of saved stack
209 mov r13, #MODE_SVC @ prepare SVC-Mode
210 @ msr spsr_c, r13
211 msr spsr, r13 @ switch modes, make sure moves will execute
212 mov lr, pc @ capture return pc
213 movs pc, lr @ jump to next instruction & switch modes.
214 .endm
215
216 .macro get_irq_stack @ setup IRQ stack
217 ldr sp, IRQ_STACK_START
218 .endm
219
220 .macro get_fiq_stack @ setup FIQ stack
221 ldr sp, FIQ_STACK_START
222 .endm
223
224/*
225 * exception handlers
226 */
227
228 .align 5
229undefined_instruction:
230 get_bad_stack
231 bad_save_user_regs
232 bl do_undefined_instruction
233
234 .align 5
235software_interrupt:
236 get_bad_stack
237 bad_save_user_regs
238 bl do_software_interrupt
239
240 .align 5
241prefetch_abort:
242 get_bad_stack
243 bad_save_user_regs
244 bl do_prefetch_abort
245
246 .align 5
247data_abort:
248 get_bad_stack
249 bad_save_user_regs
250 bl do_data_abort
251
252 .align 5
253not_used:
254 get_bad_stack
255 bad_save_user_regs
256 bl do_not_used
257
258#ifdef CONFIG_USE_IRQ
259
260 .align 5
261irq:
262 get_irq_stack
263 irq_save_user_regs
264 bl do_irq
265 irq_restore_user_regs
266
267 .align 5
268fiq:
269 get_fiq_stack
270 /* someone ought to write a more effiction fiq_save_user_regs */
271 irq_save_user_regs
272 bl do_fiq
273 irq_restore_user_regs
274
275#else
276
277 .align 5
278irq:
279 get_bad_stack
280 bad_save_user_regs
281 bl do_irq
282
283 .align 5
284fiq:
285 get_bad_stack
286 bad_save_user_regs
287 bl do_fiq
288
289#endif /* CONFIG_USE_IRQ */
290
291#endif /* CONFIG_SPL_BUILD */