1/*
2 * Copyright 2012-2022, 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 <arch/arm/arch_cpu_defs.h>
11
12#include <asm_defs.h>
13
14
15.macro DISABLE_INTERRUPTS
16	mrs		r0, cpsr
17	orr		r0, r0, #(CPSR_I | CPSR_F)
18	msr		cpsr_c, r0
19.endm
20
21/* The following two macros are taken from FreeBSD... */
22
23.macro PUSH_FRAME_IN_SVC
24	stmdb	sp, {r0-r3}					/* Save 4 registers */
25	mov		r0, lr						/* Save xxx32 r14 */
26	mov		r1, sp						/* Save xxx32 sp */
27	mrs		r3, spsr					/* Save xxx32 spsr */
28	mrs		r2, cpsr					/* Get the CPSR */
29	bic		r2, r2, #(CPSR_MODE_MASK)	/* Fix for SVC mode */
30	orr		r2, r2, #(CPSR_MODE_SVC)
31	msr		cpsr_c, r2					/* Punch into SVC mode */
32	mov		r2, sp						/* Save SVC sp */
33	str		r0, [sp, #-4]!				/* Push return address */
34	str		lr, [sp, #-4]!				/* Push SVC lr */
35	str		r2, [sp, #-4]!				/* Push SVC sp */
36	msr		spsr, r3					/* Restore correct spsr */
37	ldmdb	r1, {r0-r3}					/* Restore 4 regs from xxx mode */
38	sub		sp, sp, #(4*15)				/* Adjust the stack pointer */
39	stmia	sp, {r0-r12}				/* Push the user mode registers */
40	add		r0, sp, #(4*13)				/* Adjust the stack pointer */
41	stmia	r0, {r13-r14}^				/* Push the user mode registers */
42	mov		r0, r0						/* NOP for previous instruction */
43	mrs		r0, spsr
44	str		r0, [sp, #-4]!				/* Save spsr */
45.endm
46
47.macro PULL_FRAME_FROM_SVC_AND_EXIT
48	ldr		r0, [sp], #0x0004			/* Get the SPSR from stack */
49	msr		spsr, r0					/* restore SPSR */
50	ldmia	sp, {r0-r14}^				/* Restore registers (usr mode) */
51	mov		r0, r0						/* NOP for previous instruction */
52	add		sp, sp, #(4*15)				/* Adjust the stack pointer */
53	ldmia	sp, {sp, lr, pc}^			/* Restore lr and exit */
54.endm
55
56/* The following two macros are adapted from the two macros above, taken from FreeBSD. */
57
58.macro	PUSH_FRAME
59	str		lr, [sp, #-4]!				/* Push the return address */
60	sub		sp, sp, #(4*17)				/* Adjust the stack pointer */
61	stmia	sp, {r0-r12}				/* Store the general purpose registers */
62	add		r0, sp, #(4*13)				/* Adjust the stack pointer */
63	stmia	r0, {r13-r14}^				/* Store the user mode sp and lr registers */
64	mrs		r0, spsr					/* Store the SPSR */
65	str		r0, [sp, #-4]!
66	mov		r0, #0						/* Fill in svc mode sp and lr with zeroes */
67	str		r0, [sp, #(4*16)]
68	str		r0, [sp, #(4*17)]
69.endm
70
71.macro	PULL_FRAME_AND_EXIT
72	ldr		r0, [sp], #4				/* Get SPSR from stack */
73	msr		spsr, r0
74	ldmia	sp, {r0-r14}^				/* Restore user mode registers */
75	add		sp, sp, #(4*17)				/* Adjust the stack pointer */
76	ldr		lr, [sp], #4				/* Pull the return address */
77	movs	pc, lr						/* Return to user mode */
78.endm
79
80.text
81
82.globl _vectors_start
83_vectors_start:
84	ldr		pc, _arm_reset
85	ldr		pc, _arm_undefined
86	ldr		pc, _arm_syscall
87	ldr		pc, _arm_prefetch_abort
88	ldr		pc, _arm_data_abort
89	ldr		pc, _arm_reserved
90	ldr		pc, _arm_irq
91	ldr		pc, _arm_fiq
92
93
94_arm_reset:
95	.word	arm_reserved // actually reset, but not used when mapped
96
97_arm_undefined:
98	.word	arm_undefined
99
100_arm_syscall:
101	.word	arm_syscall
102
103_arm_prefetch_abort:
104	.word	arm_prefetch_abort
105
106_arm_data_abort:
107	.word	arm_data_abort
108
109_arm_reserved:
110	.word	arm_reserved
111
112_arm_irq:
113	.word	arm_irq
114
115_arm_fiq:
116	.word	arm_fiq
117
118
119.globl _vectors_end
120_vectors_end:
121
122.data
123
124	.rept	64
125	.word	0xdeadbeef
126	.endr
127
128abort_stack:
129	.word	. - 4
130	.word	0xdeadbeef
131
132	.rept	64
133	.word	0xcafebabe
134	.endr
135
136irq_stack:
137	.word	. - 4
138	.word	0xcafebabe
139
140	.rept	64
141	.word	0xaaaabbbb
142	.endr
143
144fiq_stack:
145	.word	. - 4
146	.word	0xaaaabbbb
147
148	.rept	64
149	.word	0xccccdddd
150	.endr
151
152und_stack:
153	.word	. - 4
154	.word	0xccccdddd
155
156.text
157
158FUNCTION(arm_undefined):
159	PUSH_FRAME_IN_SVC
160
161	mov		r0, sp		/* iframe */
162	mov		fp, r0
163	bl		arch_arm_undefined
164
165	DISABLE_INTERRUPTS
166	PULL_FRAME_FROM_SVC_AND_EXIT
167FUNCTION_END(arm_undefined)
168
169
170FUNCTION(arm_syscall):
171	PUSH_FRAME
172
173	mov		r0, sp		/* iframe */
174	mov		fp, r0
175	bl		arch_arm_syscall
176
177	DISABLE_INTERRUPTS
178	PULL_FRAME_AND_EXIT
179FUNCTION_END(arm_syscall)
180
181
182FUNCTION(arm_prefetch_abort):
183#ifdef __XSCALE__
184	nop					/* Make absolutely sure any pending */
185	nop					/* imprecise aborts have occurred. */
186#endif
187	sub		lr, lr, #4	/* Adjust LR */
188	PUSH_FRAME_IN_SVC
189
190	mov		r0, sp		/* iframe */
191	mov		fp, r0
192	bl		arch_arm_prefetch_abort
193
194	DISABLE_INTERRUPTS
195	PULL_FRAME_FROM_SVC_AND_EXIT
196FUNCTION_END(arm_prefetch_abort)
197
198
199FUNCTION(arm_data_abort):
200#ifdef __XSCALE__
201	nop					/* Make absolutely sure any pending */
202	nop					/* imprecise aborts have occurred. */
203#endif
204	sub		lr, lr, #8	/* Adjust LR */
205	PUSH_FRAME_IN_SVC
206
207	mov		r0, sp		/* iframe */
208	mov		fp, r0
209	bl		arch_arm_data_abort
210
211	DISABLE_INTERRUPTS
212	PULL_FRAME_FROM_SVC_AND_EXIT
213FUNCTION_END(arm_data_abort)
214
215
216FUNCTION(arm_reserved):
217	b	.
218FUNCTION_END(arm_reserved)
219
220
221FUNCTION(arm_irq):
222	sub		lr, lr, #4	/* Adjust LR */
223	PUSH_FRAME_IN_SVC
224
225	mov		r0, sp		/* iframe */
226	mov		fp, r0
227	bl		arch_arm_irq
228
229	DISABLE_INTERRUPTS
230	PULL_FRAME_FROM_SVC_AND_EXIT
231FUNCTION_END(arm_irq)
232
233
234FUNCTION(arm_fiq):
235	sub		lr, lr, #4	/* Adjust LR */
236	PUSH_FRAME_IN_SVC
237
238	mov		r0, sp		/* iframe */
239	mov		fp, r0
240	bl		arch_arm_fiq
241
242	DISABLE_INTERRUPTS
243	PULL_FRAME_FROM_SVC_AND_EXIT
244FUNCTION_END(arm_fiq)
245
246
247
248FUNCTION(arm_vector_init):
249	mrs	r1, cpsr
250	bic	r1, r1, #CPSR_MODE_MASK
251
252	/* move into modes and set initial sp */
253	mov	r0, r1
254	orr	r0, r0, #CPSR_MODE_FIQ
255	msr	cpsr_c, r0
256	ldr r2, =fiq_stack
257	ldr sp, [r2]
258
259	mov	r0, r1
260	orr	r0, r0, #CPSR_MODE_IRQ
261	msr	cpsr_c, r0
262	ldr r2, =irq_stack
263	ldr sp, [r2]
264
265	mov	r0, r1
266	orr	r0, r0, #CPSR_MODE_ABT
267	msr	cpsr_c, r0
268	ldr r2, =abort_stack
269	ldr sp, [r2]
270
271	mov	r0, r1
272	orr	r0, r0, #CPSR_MODE_UND
273	msr	cpsr_c, r0
274	ldr r2, =und_stack
275	ldr sp, [r2]
276
277	/* ... and return back to supervisor mode */
278	mov	r0, r1
279	orr	r0, r0, #CPSR_MODE_SVC
280	msr	cpsr_c, r0
281
282	bx	lr
283FUNCTION_END(arm_vector_init)
284