xref: /haiku/src/system/kernel/arch/arm/arch_exceptions.S (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1/*
2 * Copyright 2012, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ithamar R. Adema <ithamar@upgrade-android.com>
7 *
8 */
9
10#include <asm_defs.h>
11
12#define CPSR_MODE_MASK	0x1f
13#define CPSR_MODE_USR	0x10
14#define CPSR_MODE_FIQ	0x11
15#define CPSR_MODE_IRQ	0x12
16#define CPSR_MODE_SVC	0x13
17#define CPSR_MODE_ABT	0x17
18#define CPSR_MODE_UND	0x1b
19
20/* The following two macros are taken from FreeBSD... */
21
22.macro PUSHFRAMEINSVC
23	stmdb	sp, {r0-r3}					/* Save 4 registers */
24	mov		r0, lr						/* Save xxx32 r14 */
25	mov		r1, sp						/* Save xxx32 sp */
26	mrs		r3, spsr					/* Save xxx32 spsr */
27	mrs		r2, cpsr					/* Get the CPSR */
28	bic		r2, r2, #(CPSR_MODE_MASK)	/* Fix for SVC mode */
29	orr		r2, r2, #(CPSR_MODE_SVC)
30	msr		cpsr_c, r2					/* Punch into SVC mode */
31	mov		r2, sp						/* Save SVC sp */
32	str		r0, [sp, #-4]!				/* Push return address */
33	str		lr, [sp, #-4]!				/* Push SVC lr */
34	str		r2, [sp, #-4]!				/* Push SVC sp */
35	msr		spsr_all, r3				/* Restore correct spsr */
36	ldmdb	r1, {r0-r3}					/* Restore 4 regs from xxx mode */
37	sub		sp, sp, #(4*15)				/* Adjust the stack pointer */
38	stmia	sp, {r0-r12}				/* Push the user mode registers */
39	add		r0, sp, #(4*13)				/* Adjust the stack pointer */
40	stmia	r0, {r13-r14}^				/* Push the user mode registers */
41	mov		r0, r0						/* NOP for previous instruction */
42	mrs		r0, spsr_all
43	str		r0, [sp, #-4]!				/* Save spsr */
44.endm
45
46.macro PULLFRAMEFROMSVCANDEXIT
47	ldr		r0, [sp], #0x0004			/* Get the SPSR from stack */
48	msr		spsr_all, r0				/* restore SPSR */
49	ldmia	sp, {r0-r14}^				/* Restore registers (usr mode) */
50	mov		r0, r0						/* NOP for previous instruction */
51	add		sp, sp, #(4*15)				/* Adjust the stack pointer */
52	ldmia	sp, {sp, lr, pc}^			/* Restore lr and exit */
53.endm
54
55.text
56
57.globl _vectors_start
58_vectors_start:
59	ldr		pc, _arm_reset
60	ldr		pc, _arm_undefined
61	ldr		pc, _arm_syscall
62	ldr		pc, _arm_prefetch_abort
63	ldr		pc, _arm_data_abort
64	ldr		pc, _arm_reserved
65	ldr		pc, _arm_irq
66	ldr		pc, _arm_fiq
67
68
69_arm_reset:
70	.word	arm_reserved // actually reset, but not used when mapped
71
72_arm_undefined:
73	.word	arm_undefined
74
75_arm_syscall:
76	.word	arm_syscall
77
78_arm_prefetch_abort:
79	.word	arm_prefetch_abort
80
81_arm_data_abort:
82	.word	arm_data_abort
83
84_arm_reserved:
85	.word	arm_reserved
86
87_arm_irq:
88	.word	arm_irq
89
90_arm_fiq:
91	.word	arm_fiq
92
93
94.globl _vectors_end
95_vectors_end:
96	.rept	64
97	.word	0xdeadbeef
98	.endr
99
100abort_stack:
101	.word	. - 4
102	.word	0xdeadbeef
103
104	.rept	64
105	.word	0xcafebabe
106	.endr
107
108irq_stack:
109	.word	. - 4
110	.word	0xcafebabe
111
112	.rept	64
113	.word	0xaaaabbbb
114	.endr
115
116fiq_stack:
117	.word	. - 4
118	.word	0xaaaabbbb
119
120	.rept	64
121	.word	0xccccdddd
122	.endr
123
124und_stack:
125	.word	. - 4
126	.word	0xccccdddd
127
128
129FUNCTION(arm_undefined):
130	PUSHFRAMEINSVC
131
132	mov	r0, sp
133	bl	arch_arm_undefined
134
135	PULLFRAMEFROMSVCANDEXIT
136FUNCTION_END(arm_undefined)
137
138
139FUNCTION(arm_syscall):
140	PUSHFRAMEINSVC
141
142	mov	r0, sp
143	bl	arch_arm_syscall
144
145	PULLFRAMEFROMSVCANDEXIT
146FUNCTION_END(arm_syscall)
147
148
149FUNCTION(arm_prefetch_abort):
150#ifdef __XSCALE__
151	nop					/* Make absolutely sure any pending */
152	nop					/* imprecise aborts have occurred. */
153#endif
154 	add	lr, lr, #4
155	PUSHFRAMEINSVC
156
157	mov	r0, sp
158	bl	arch_arm_prefetch_abort
159
160	PULLFRAMEFROMSVCANDEXIT
161FUNCTION_END(arm_prefetch_abort)
162
163
164FUNCTION(arm_data_abort):
165#ifdef __XSCALE__
166	nop					/* Make absolutely sure any pending */
167	nop					/* imprecise aborts have occurred. */
168#endif
169	sub	lr, lr, #8		/* Adjust the lr */
170	PUSHFRAMEINSVC
171
172	mov	r0, sp
173	bl	arch_arm_data_abort
174
175	PULLFRAMEFROMSVCANDEXIT
176FUNCTION_END(arm_data_abort)
177
178
179FUNCTION(arm_reserved):
180	b	.
181FUNCTION_END(arm_reserved)
182
183
184FUNCTION(arm_irq):
185	sub	lr, lr, #4
186	PUSHFRAMEINSVC
187
188	mov	r0, sp			/* iframe */
189	bl	arch_arm_irq
190
191	PULLFRAMEFROMSVCANDEXIT
192FUNCTION_END(arm_irq)
193
194
195FUNCTION(arm_fiq):
196	sub	lr, lr, #4
197	PUSHFRAMEINSVC
198
199	mov	r0, sp			/* iframe */
200	bl	arch_arm_fiq
201
202	PULLFRAMEFROMSVCANDEXIT
203FUNCTION_END(arm_fiq)
204
205
206
207FUNCTION(arm_vector_init):
208	mrs	r1, cpsr
209	bic	r1, r1, #CPSR_MODE_MASK
210
211	/* move into modes and set initial sp */
212	mov	r0, r1
213	orr	r0, r0, #CPSR_MODE_FIQ
214	msr	cpsr_c, r0
215	ldr	sp, fiq_stack
216
217	mov	r0, r1
218	orr	r0, r0, #CPSR_MODE_IRQ
219	msr	cpsr_c, r0
220	ldr	sp, irq_stack
221
222	mov	r0, r1
223	orr	r0, r0, #CPSR_MODE_ABT
224	msr	cpsr_c, r0
225	ldr	sp, abort_stack
226
227	mov	r0, r1
228	orr	r0, r0, #CPSR_MODE_UND
229	msr	cpsr_c, r0
230	ldr	sp, und_stack
231
232	/* ... and return back to supervisor mode */
233	mov	r0, r1
234	orr	r0, r0, #CPSR_MODE_SVC
235	msr	cpsr_c, r0
236
237	bx	lr
238FUNCTION_END(arm_vector_init)
239