exception.S revision 1.11 1 1.11 scw /* $NetBSD: exception.S,v 1.11 2003/10/26 11:34:29 scw Exp $ */
2 1.1 chris
3 1.1 chris /*
4 1.1 chris * Copyright (c) 1994-1997 Mark Brinicombe.
5 1.1 chris * Copyright (c) 1994 Brini.
6 1.1 chris * All rights reserved.
7 1.1 chris *
8 1.1 chris * This code is derived from software written for Brini by Mark Brinicombe
9 1.1 chris *
10 1.1 chris * Redistribution and use in source and binary forms, with or without
11 1.1 chris * modification, are permitted provided that the following conditions
12 1.1 chris * are met:
13 1.1 chris * 1. Redistributions of source code must retain the above copyright
14 1.1 chris * notice, this list of conditions and the following disclaimer.
15 1.1 chris * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 chris * notice, this list of conditions and the following disclaimer in the
17 1.1 chris * documentation and/or other materials provided with the distribution.
18 1.1 chris * 3. All advertising materials mentioning features or use of this software
19 1.1 chris * must display the following acknowledgement:
20 1.1 chris * This product includes software developed by Brini.
21 1.1 chris * 4. The name of the company nor the name of the author may be used to
22 1.1 chris * endorse or promote products derived from this software without specific
23 1.1 chris * prior written permission.
24 1.1 chris *
25 1.1 chris * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 1.1 chris * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 1.1 chris * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 1.1 chris * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 1.1 chris * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 1.1 chris * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 1.1 chris * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.1 chris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.1 chris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.1 chris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.1 chris * SUCH DAMAGE.
36 1.1 chris *
37 1.1 chris * RiscBSD kernel project
38 1.1 chris *
39 1.1 chris * exception.S
40 1.1 chris *
41 1.1 chris * Low level handlers for exception vectors
42 1.1 chris *
43 1.1 chris * Created : 24/09/94
44 1.1 chris *
45 1.1 chris * Based on kate/display/abort.s
46 1.1 chris */
47 1.1 chris
48 1.1 chris #include "opt_ipkdb.h"
49 1.9 scw #include "opt_compat_netbsd.h"
50 1.9 scw #include "opt_execfmt.h"
51 1.9 scw #include "opt_multiprocessor.h"
52 1.1 chris #include <machine/asm.h>
53 1.1 chris #include <machine/cpu.h>
54 1.1 chris #include <machine/frame.h>
55 1.1 chris #include "assym.h"
56 1.1 chris
57 1.1 chris .text
58 1.1 chris .align 0
59 1.1 chris
60 1.9 scw .Lastpending:
61 1.9 scw .word _C_LABEL(astpending)
62 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
63 1.9 scw .Lcpufuncs:
64 1.9 scw .word _C_LABEL(cpufuncs)
65 1.9 scw #ifndef MULTIPROCESSOR
66 1.9 scw .Lcurpcb:
67 1.9 scw .word _C_LABEL(curpcb)
68 1.9 scw .Lcpu_info_store:
69 1.9 scw .word _C_LABEL(cpu_info_store)
70 1.9 scw #define GET_CURPCB \
71 1.9 scw ldr r1, .Lcurpcb ;\
72 1.9 scw ldr r1, [r1]
73 1.9 scw #define GET_CPUINFO \
74 1.9 scw ldr r0, .Lcpu_info_store
75 1.9 scw #else
76 1.9 scw .Lcpu_info:
77 1.9 scw .word _C_LABEL(cpu_info)
78 1.9 scw #define GET_CURPCB \
79 1.9 scw ldr r4, .Lcpu_info ;\
80 1.9 scw bl _C_LABEL(cpu_number) ;\
81 1.9 scw ldr r0, [r4, r0, lsl #2] ;\
82 1.9 scw ldr r1, [r0, #CI_CURPCB]
83 1.9 scw #define GET_CPUINFO /* nothing to do */
84 1.9 scw #endif
85 1.9 scw #define ENABLE_ALIGNMENT_FAULTS \
86 1.9 scw GET_CURPCB ;\
87 1.11 scw cmp r1, #0x00 /* curpcb NULL? ;\
88 1.11 scw ldrne r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */ ;\
89 1.11 scw tstne r1, #PCB_NOALIGNFLT ;\
90 1.9 scw beq 1f /* Alignment faults already enabled */ ;\
91 1.9 scw GET_CPUINFO ;\
92 1.9 scw ldr r2, .Lcpufuncs ;\
93 1.9 scw ldr r1, [r0, #CI_CTRL] /* Fetch control register */ ;\
94 1.9 scw mov r0, #-1 ;\
95 1.9 scw mov lr, pc ;\
96 1.9 scw ldr pc, [r2, #CF_CONTROL] /* Enable alignment faults */ ;\
97 1.9 scw 1:
98 1.9 scw #endif /* COMPAT_15 && EXEC_AOUT */
99 1.9 scw
100 1.1 chris
101 1.1 chris /*
102 1.1 chris * General exception exit handler
103 1.1 chris *
104 1.1 chris * It exits straight away if not returning to USR mode.
105 1.1 chris * This loops around delivering any pending ASTs.
106 1.1 chris * Interrupts are disabled at suitable points to avoid ASTs
107 1.1 chris * being posted between testing and exit to user mode.
108 1.1 chris *
109 1.1 chris * This function uses PULLFRAMEFROMSVCANDEXIT thus should
110 1.1 chris * only be called if the exception handler used PUSHFRAMEINSVC
111 1.1 chris */
112 1.1 chris
113 1.1 chris exception_exit:
114 1.6 briggs mrs r4, cpsr /* Get CPSR */
115 1.1 chris
116 1.1 chris ldr r0, [sp] /* Get the SPSR from stack */
117 1.1 chris and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the AST */
118 1.1 chris teq r0, #(PSR_USR32_MODE)
119 1.6 briggs bne .Ldo_exit /* Not USR mode so no AST delivery */
120 1.1 chris
121 1.9 scw ldr r5, .Lastpending /* Get address of astpending */
122 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
123 1.9 scw ldr r6, .Lcurpcb
124 1.9 scw ldr r7, .Lcpu_info_store
125 1.9 scw #endif
126 1.1 chris
127 1.1 chris Lexception_exit_loop:
128 1.1 chris orr r0, r4, #(I32_bit) /* Block IRQs */
129 1.1 chris msr cpsr_all, r0
130 1.1 chris
131 1.1 chris ldr r1, [r5] /* Do we have an AST pending */
132 1.1 chris teq r1, #0x00000000
133 1.6 briggs bne .Ldo_ast
134 1.1 chris
135 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
136 1.9 scw /* Disable alignment faults for the process, if necessary. */
137 1.9 scw #ifdef MULTIPROCESSOR
138 1.9 scw ldr r7, .Lcpu_info
139 1.9 scw bl _C_LABEL(cpu_number)
140 1.9 scw ldr r7, [r7, r0, lsl #2]
141 1.9 scw ldr r1, [r7, #CI_CURPCB]
142 1.9 scw #else
143 1.9 scw ldr r1, [r6]
144 1.9 scw #endif
145 1.11 scw cmp r1, #0x00 /* curpcb NULL? */
146 1.11 scw ldrne r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
147 1.11 scw tstne r1, #PCB_NOALIGNFLT
148 1.9 scw beq 1f /* Keep alignment faults enabled */
149 1.9 scw ldr r1, [r7, #CI_CTRL] /* Fetch control register */
150 1.9 scw ldr r2, .Lcpufuncs
151 1.9 scw mov r0, #-1
152 1.9 scw bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
153 1.9 scw mov lr, pc
154 1.9 scw ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
155 1.9 scw 1:
156 1.9 scw #endif
157 1.9 scw
158 1.1 chris PULLFRAMEFROMSVCANDEXIT /* No AST so exit */
159 1.1 chris
160 1.6 briggs .Ldo_ast:
161 1.1 chris mov r1, #0x00000000 /* Clear ast pending */
162 1.1 chris str r1, [r5]
163 1.1 chris
164 1.2 thorpej msr cpsr_all, r4 /* Restore interrupts */
165 1.2 thorpej
166 1.1 chris mov r0, sp /* arg 0 = trap frame */
167 1.1 chris bl _C_LABEL(ast) /* call the AST handler */
168 1.1 chris b Lexception_exit_loop /* Try and exit again */
169 1.1 chris
170 1.6 briggs .Ldo_exit:
171 1.8 wiz orr r0, r4, #(I32_bit) /* Disable interrupts */
172 1.1 chris msr cpsr_all, r0
173 1.1 chris
174 1.1 chris PULLFRAMEFROMSVCANDEXIT /* Restore the trap frame and exit */
175 1.1 chris
176 1.3 thorpej /*
177 1.3 thorpej * reset_entry:
178 1.3 thorpej *
179 1.3 thorpej * Handler for Reset exception.
180 1.3 thorpej */
181 1.3 thorpej ASENTRY_NP(reset_entry)
182 1.3 thorpej adr r0, Lreset_panicmsg
183 1.3 thorpej mov r1, lr
184 1.3 thorpej bl _C_LABEL(panic)
185 1.3 thorpej /* NOTREACHED */
186 1.3 thorpej Lreset_panicmsg:
187 1.3 thorpej .asciz "Reset vector called, LR = 0x%08x"
188 1.3 thorpej .balign 4
189 1.1 chris
190 1.3 thorpej /*
191 1.3 thorpej * swi_entry
192 1.3 thorpej *
193 1.3 thorpej * Handler for the Software Interrupt exception.
194 1.3 thorpej */
195 1.3 thorpej ASENTRY_NP(swi_entry)
196 1.3 thorpej PUSHFRAME
197 1.3 thorpej
198 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
199 1.9 scw ENABLE_ALIGNMENT_FAULTS
200 1.9 scw #endif
201 1.9 scw
202 1.3 thorpej mov r0, sp /* Pass the frame to any function */
203 1.1 chris
204 1.5 bjh21 bl _C_LABEL(swi_handler) /* It's a SWI ! */
205 1.1 chris
206 1.9 scw ldr r5, .Lastpending /* Get address of astpending */
207 1.6 briggs mrs r4, cpsr /* Get CPSR */
208 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
209 1.9 scw ldr r6, .Lcurpcb
210 1.9 scw ldr r7, .Lcpu_info_store
211 1.9 scw #endif
212 1.1 chris
213 1.6 briggs .Lswi_exit_loop:
214 1.3 thorpej orr r0, r4, #(I32_bit) /* Disable IRQs */
215 1.3 thorpej msr cpsr_all, r0
216 1.1 chris
217 1.3 thorpej ldr r1, [r5] /* Do we have an AST pending */
218 1.3 thorpej teq r1, #0x00000000
219 1.6 briggs bne .Ldo_swi_ast
220 1.1 chris
221 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
222 1.9 scw /* Disable alignment faults for the process, if necessary. */
223 1.9 scw #ifdef MULTIPROCESSOR
224 1.9 scw ldr r7, .Lcpu_info
225 1.9 scw bl _C_LABEL(cpu_number)
226 1.9 scw ldr r7, [r7, r0, lsl #2]
227 1.9 scw ldr r1, [r7, #CI_CURPCB]
228 1.9 scw #else
229 1.9 scw ldr r1, [r6]
230 1.9 scw #endif
231 1.11 scw cmp r1, #0x00 /* curpcb NULL? */
232 1.11 scw ldrne r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
233 1.11 scw tstne r1, #PCB_NOALIGNFLT
234 1.9 scw beq 1f /* Keep alignment faults enabled */
235 1.9 scw ldr r1, [r7, #CI_CTRL] /* Fetch control register */
236 1.9 scw ldr r2, .Lcpufuncs
237 1.9 scw mov r0, #-1
238 1.9 scw bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
239 1.9 scw mov lr, pc
240 1.9 scw ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
241 1.9 scw 1:
242 1.9 scw #endif
243 1.3 thorpej PULLFRAME
244 1.3 thorpej movs pc, lr /* Exit */
245 1.1 chris
246 1.6 briggs .Ldo_swi_ast:
247 1.3 thorpej mov r1, #0x00000000 /* Clear ast pending */
248 1.3 thorpej str r1, [r5]
249 1.1 chris
250 1.3 thorpej msr cpsr_all, r4 /* Restore interrupts */
251 1.1 chris
252 1.3 thorpej mov r0, sp /* arg 0 = trap frame */
253 1.3 thorpej bl _C_LABEL(ast) /* call the AST handler */
254 1.6 briggs b .Lswi_exit_loop /* Try and exit again */
255 1.1 chris
256 1.3 thorpej /*
257 1.3 thorpej * prefetch_abort_entry:
258 1.3 thorpej *
259 1.3 thorpej * Handler for the Prefetch Abort exception.
260 1.3 thorpej */
261 1.1 chris ASENTRY_NP(prefetch_abort_entry)
262 1.1 chris sub lr, lr, #0x00000004 /* Adjust the lr */
263 1.1 chris
264 1.1 chris PUSHFRAMEINSVC
265 1.1 chris
266 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
267 1.9 scw ENABLE_ALIGNMENT_FAULTS
268 1.9 scw #endif
269 1.9 scw
270 1.1 chris mov r0, sp /* pass the stack pointer as r0 */
271 1.1 chris
272 1.7 bjh21 adr lr, exception_exit
273 1.1 chris ldr r1, Lprefetch_abort_handler_address
274 1.1 chris ldr pc, [r1]
275 1.1 chris
276 1.1 chris Lprefetch_abort_handler_address:
277 1.1 chris .word _C_LABEL(prefetch_abort_handler_address)
278 1.1 chris
279 1.1 chris .data
280 1.1 chris .global _C_LABEL(prefetch_abort_handler_address)
281 1.1 chris
282 1.1 chris _C_LABEL(prefetch_abort_handler_address):
283 1.1 chris .word abortprefetch
284 1.1 chris
285 1.1 chris .text
286 1.1 chris abortprefetch:
287 1.7 bjh21 adr r0, abortprefetchmsg
288 1.1 chris b _C_LABEL(panic)
289 1.1 chris
290 1.1 chris abortprefetchmsg:
291 1.1 chris .asciz "abortprefetch"
292 1.1 chris .align 0
293 1.1 chris
294 1.1 chris /*
295 1.3 thorpej * data_abort_entry:
296 1.1 chris *
297 1.3 thorpej * Handler for the Data Abort exception.
298 1.1 chris */
299 1.3 thorpej ASENTRY_NP(data_abort_entry)
300 1.3 thorpej sub lr, lr, #0x00000008 /* Adjust the lr */
301 1.1 chris
302 1.3 thorpej PUSHFRAMEINSVC /* Push trap frame and switch */
303 1.3 thorpej /* to SVC32 mode */
304 1.1 chris
305 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
306 1.10 scw and r0, r0, #(PSR_MODE) /* Test for USR32 mode (r0 = spsr_all)*/
307 1.10 scw teq r0, #(PSR_USR32_MODE)
308 1.10 scw bne 99f /* Not USR mode so skip AFLT check */
309 1.9 scw ENABLE_ALIGNMENT_FAULTS
310 1.10 scw 99:
311 1.9 scw #endif
312 1.9 scw
313 1.3 thorpej mov r0, sp /* pass the stack pointer as r0 */
314 1.1 chris
315 1.7 bjh21 adr lr, exception_exit
316 1.3 thorpej ldr r1, Ldata_abort_handler_address
317 1.3 thorpej ldr pc, [r1]
318 1.1 chris
319 1.3 thorpej Ldata_abort_handler_address:
320 1.3 thorpej .word _C_LABEL(data_abort_handler_address)
321 1.1 chris
322 1.3 thorpej .data
323 1.3 thorpej .global _C_LABEL(data_abort_handler_address)
324 1.3 thorpej _C_LABEL(data_abort_handler_address):
325 1.3 thorpej .word abortdata
326 1.1 chris
327 1.3 thorpej .text
328 1.3 thorpej abortdata:
329 1.7 bjh21 adr r0, abortdatamsg
330 1.3 thorpej b _C_LABEL(panic)
331 1.1 chris
332 1.3 thorpej abortdatamsg:
333 1.3 thorpej .asciz "abortdata"
334 1.3 thorpej .align 0
335 1.1 chris
336 1.3 thorpej /*
337 1.3 thorpej * address_exception_entry:
338 1.3 thorpej *
339 1.3 thorpej * Handler for the Address Exception exception.
340 1.3 thorpej *
341 1.3 thorpej * NOTE: This exception isn't really used on arm32. We
342 1.3 thorpej * print a warning message to the console and then treat
343 1.3 thorpej * it like a Data Abort.
344 1.3 thorpej */
345 1.3 thorpej ASENTRY_NP(address_exception_entry)
346 1.3 thorpej mrs r1, cpsr_all
347 1.3 thorpej mrs r2, spsr_all
348 1.3 thorpej mov r3, lr
349 1.3 thorpej adr r0, Laddress_exception_msg
350 1.3 thorpej bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */
351 1.3 thorpej b data_abort_entry
352 1.3 thorpej Laddress_exception_msg:
353 1.3 thorpej .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
354 1.3 thorpej .balign 4
355 1.1 chris
356 1.1 chris /*
357 1.3 thorpej * undefined_entry:
358 1.3 thorpej *
359 1.3 thorpej * Handler for the Undefined Instruction exception.
360 1.3 thorpej *
361 1.3 thorpej * We indirect the undefined vector via the handler address
362 1.3 thorpej * in the data area. Entry to the undefined handler must
363 1.3 thorpej * look like direct entry from the vector.
364 1.1 chris */
365 1.1 chris ASENTRY_NP(undefined_entry)
366 1.1 chris #ifdef IPKDB
367 1.1 chris /*
368 1.1 chris * IPKDB must be hooked in at the earliest possible entry point.
369 1.1 chris *
370 1.1 chris */
371 1.1 chris /*
372 1.1 chris * Make room for all registers saving real r0-r7 and r15.
373 1.1 chris * The remaining registers are updated later.
374 1.1 chris */
375 1.1 chris stmfd sp!, {r0,r1} /* psr & spsr */
376 1.1 chris stmfd sp!, {lr} /* pc */
377 1.1 chris stmfd sp!, {r0-r14} /* r0-r7, r8-r14 */
378 1.1 chris /*
379 1.1 chris * Get previous psr.
380 1.1 chris */
381 1.1 chris mrs r7, cpsr_all
382 1.1 chris mrs r0, spsr_all
383 1.1 chris str r0, [sp, #(16*4)]
384 1.1 chris /*
385 1.1 chris * Test for user mode.
386 1.1 chris */
387 1.1 chris tst r0, #0xf
388 1.6 briggs bne .Lprenotuser_push
389 1.1 chris add r1, sp, #(8*4)
390 1.1 chris stmia r1,{r8-r14}^ /* store user mode r8-r14*/
391 1.6 briggs b .Lgoipkdb
392 1.1 chris /*
393 1.1 chris * Switch to previous mode to get r8-r13.
394 1.1 chris */
395 1.6 briggs .Lprenotuser_push:
396 1.1 chris orr r0, r0, #(I32_bit) /* disable interrupts */
397 1.1 chris msr cpsr_all, r0
398 1.1 chris mov r1, r8
399 1.1 chris mov r2, r9
400 1.1 chris mov r3, r10
401 1.1 chris mov r4, r11
402 1.1 chris mov r5, r12
403 1.1 chris mov r6, r13
404 1.1 chris msr cpsr_all, r7 /* back to undefined mode */
405 1.1 chris add r8, sp, #(8*4)
406 1.1 chris stmia r8, {r1-r6} /* r8-r13 */
407 1.1 chris /*
408 1.1 chris * Now back to previous mode to get r14 and spsr.
409 1.1 chris */
410 1.1 chris msr cpsr_all, r0
411 1.1 chris mov r1, r14
412 1.1 chris mrs r2, spsr
413 1.1 chris msr cpsr_all, r7 /* back to undefined mode */
414 1.1 chris str r1, [sp, #(14*4)] /* r14 */
415 1.1 chris str r2, [sp, #(17*4)] /* spsr */
416 1.1 chris /*
417 1.1 chris * Now to IPKDB.
418 1.1 chris */
419 1.6 briggs .Lgoipkdb:
420 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
421 1.9 scw ENABLE_ALIGNMENT_FAULTS
422 1.9 scw #endif
423 1.1 chris mov r0, sp
424 1.1 chris bl _C_LABEL(ipkdb_trap_glue)
425 1.6 briggs ldr r1, .Lipkdb_trap_return
426 1.1 chris str r0,[r1]
427 1.9 scw
428 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
429 1.9 scw #ifdef MULTIPROCESSOR
430 1.9 scw ldr r7, .Lcpu_info
431 1.9 scw bl _C_LABEL(cpu_number)
432 1.9 scw ldr r7, [r7, r0, lsl #2]
433 1.9 scw ldr r1, [r7, #CI_CURPCB]
434 1.9 scw #else
435 1.9 scw ldr r6, .Lcurpcb
436 1.9 scw ldr r7, .Lcpu_info_store
437 1.9 scw ldr r1, [r6]
438 1.9 scw #endif
439 1.11 scw cmp r1, #0x00 /* curpcb NULL? */
440 1.11 scw ldrne r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
441 1.11 scw tstne r1, #PCB_NOALIGNFLT
442 1.9 scw beq 1f /* Keep alignment faults enabled */
443 1.9 scw ldr r1, [r7, #CI_CTRL] /* Fetch control register */
444 1.9 scw ldr r2, .Lcpufuncs
445 1.9 scw mov r0, #-1
446 1.9 scw bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
447 1.9 scw mov lr, pc
448 1.9 scw ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
449 1.9 scw 1:
450 1.9 scw #endif
451 1.9 scw
452 1.1 chris /*
453 1.1 chris * Have to load all registers from the stack.
454 1.1 chris *
455 1.1 chris * Start with spsr and pc.
456 1.1 chris */
457 1.1 chris ldr r0, [sp, #(16*4)] /* spsr */
458 1.1 chris ldr r1, [sp, #(15*4)] /* r15 */
459 1.1 chris msr spsr_all, r0
460 1.1 chris mov r14, r1
461 1.1 chris /*
462 1.1 chris * Test for user mode.
463 1.1 chris */
464 1.1 chris tst r0, #0xf
465 1.6 briggs bne .Lprenotuser_pull
466 1.1 chris add r1, sp, #(8*4)
467 1.1 chris ldmia r1, {r8-r14}^ /* load user mode r8-r14 */
468 1.6 briggs b .Lpull_r0r7
469 1.6 briggs .Lprenotuser_pull:
470 1.1 chris /*
471 1.1 chris * Now previous mode spsr and r14.
472 1.1 chris */
473 1.1 chris ldr r1, [sp, #(17*4)] /* spsr */
474 1.1 chris ldr r2, [sp, #(14*4)] /* r14 */
475 1.1 chris orr r0, r0, #(I32_bit)
476 1.1 chris msr cpsr_all, r0 /* switch to previous mode */
477 1.1 chris msr spsr_all, r1
478 1.1 chris mov r14, r2
479 1.1 chris msr cpsr_all, r7 /* back to undefined mode */
480 1.1 chris /*
481 1.1 chris * Now r8-r13.
482 1.1 chris */
483 1.1 chris add r8, sp, #(8*4)
484 1.1 chris ldmia r8, {r1-r6} /* r8-r13 */
485 1.1 chris msr cpsr_all, r0
486 1.1 chris mov r8, r1
487 1.1 chris mov r9, r2
488 1.1 chris mov r10, r3
489 1.1 chris mov r11, r4
490 1.1 chris mov r12, r5
491 1.1 chris mov r13, r6
492 1.1 chris msr cpsr_all, r7
493 1.6 briggs .Lpull_r0r7:
494 1.1 chris /*
495 1.1 chris * Now the rest of the registers.
496 1.1 chris */
497 1.1 chris ldr r1,Lipkdb_trap_return
498 1.1 chris ldr r0,[r1]
499 1.1 chris tst r0,r0
500 1.1 chris ldmfd sp!, {r0-r7} /* r0-r7 */
501 1.1 chris add sp, sp, #(10*4) /* adjust sp */
502 1.1 chris
503 1.1 chris /*
504 1.1 chris * Did IPKDB handle it?
505 1.1 chris */
506 1.1 chris movnes pc, lr /* return */
507 1.1 chris
508 1.1 chris #endif
509 1.1 chris stmfd sp!, {r0, r1}
510 1.1 chris ldr r0, Lundefined_handler_indirection
511 1.1 chris ldr r1, [sp], #0x0004
512 1.1 chris str r1, [r0, #0x0000]
513 1.1 chris ldr r1, [sp], #0x0004
514 1.1 chris str r1, [r0, #0x0004]
515 1.1 chris ldmia r0, {r0, r1, pc}
516 1.1 chris
517 1.1 chris #ifdef IPKDB
518 1.1 chris Lipkdb_trap_return:
519 1.1 chris .word Lipkdb_trap_return_data
520 1.1 chris #endif
521 1.1 chris
522 1.1 chris Lundefined_handler_indirection:
523 1.1 chris .word Lundefined_handler_indirection_data
524 1.1 chris
525 1.1 chris /*
526 1.1 chris * assembly bounce code for calling the kernel
527 1.1 chris * undefined instruction handler. This uses
528 1.1 chris * a standard trap frame and is called in SVC mode.
529 1.1 chris */
530 1.1 chris
531 1.1 chris ENTRY_NP(undefinedinstruction_bounce)
532 1.1 chris PUSHFRAMEINSVC
533 1.9 scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
534 1.10 scw and r0, r0, #(PSR_MODE) /* Test for USR32 mode (r0 = spsr_all)*/
535 1.10 scw teq r0, #(PSR_USR32_MODE)
536 1.10 scw bne 99f /* Not USR mode so skip AFLT check */
537 1.9 scw ENABLE_ALIGNMENT_FAULTS
538 1.10 scw 99:
539 1.9 scw #endif
540 1.1 chris mov r0, sp
541 1.1 chris bl _C_LABEL(undefinedinstruction)
542 1.1 chris
543 1.1 chris b exception_exit
544 1.1 chris
545 1.1 chris .data
546 1.1 chris .align 0
547 1.1 chris
548 1.1 chris #ifdef IPKDB
549 1.1 chris Lipkdb_trap_return_data:
550 1.1 chris .word 0
551 1.1 chris #endif
552 1.1 chris
553 1.1 chris /*
554 1.1 chris * Indirection data
555 1.1 chris * 2 words use for preserving r0 and r1
556 1.1 chris * 3rd word contains the undefined handler address.
557 1.1 chris */
558 1.1 chris
559 1.1 chris Lundefined_handler_indirection_data:
560 1.1 chris .word 0
561 1.1 chris .word 0
562 1.1 chris
563 1.1 chris .global _C_LABEL(undefined_handler_address)
564 1.1 chris _C_LABEL(undefined_handler_address):
565 1.1 chris .word _C_LABEL(undefinedinstruction_bounce)
566