1 /* $NetBSD: armfpe_glue.S,v 1.2.22.3 2004/09/21 13:13:19 skrll Exp $ */
4 * Copyright (c) 1996 Mark Brinicombe
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Mark Brinicombe.
18 * 4. The name of the company nor the name of the author may be used to
19 * endorse or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * RiscBSD kernel project
38 * Glue code for calling the ARM FPE core code
43 #define CHECK_BEFORE_USERRET
45 #include <machine/asm.h>
46 #include <machine/cpu.h>
49 * Glue for calling the core entry points
52 ENTRY_NP(arm_fpe_core_disable)
53 stmfd sp!, {r0-r7, lr}
54 bl _C_LABEL(fpe_arm_core_disable)
55 ldmfd sp!, {r0-r7, pc}
57 ENTRY_NP(arm_fpe_core_enable)
58 stmfd sp!, {r0-r7, lr}
59 bl _C_LABEL(fpe_arm_core_enable)
60 ldmfd sp!, {r0-r7, pc}
62 ENTRY_NP(arm_fpe_core_initws)
65 bl _C_LABEL(fpe_arm_core_initws)
68 ENTRY_NP(arm_fpe_core_abort)
69 stmfd sp!, {r1-r7, r10, lr}
73 bl _C_LABEL(fpe_arm_core_abort)
74 ldmfd sp!, {r1-r7, r10, pc}
76 /* Only needs to preserve r10 */
78 ENTRY_NP(arm_fpe_core_initcontext)
79 stmfd sp!, {r0-r7, r10, lr}
81 bl _C_LABEL(fpe_arm_core_initcontext)
82 ldmfd sp!, {r0-r7, r10, pc}
84 /* Only needs to preserve r10 */
86 ENTRY_NP(arm_fpe_core_changecontext)
87 stmfd sp!, {r1-r7, r10, lr}
89 bl _C_LABEL(fpe_arm_core_changecontext)
90 ldmfd sp!, {r1-r7, r10, pc}
92 /* All regs preserved */
94 ENTRY_NP(arm_fpe_core_shutdown)
95 stmfd sp!, {r0-r7, r10, lr}
96 bl _C_LABEL(fpe_arm_core_shutdown)
97 ldmfd sp!, {r0-r7, r10, pc}
101 ENTRY_NP(arm_fpe_core_savecontext)
102 stmfd sp!, {r1-r7, r10, lr}
106 bl _C_LABEL(fpe_arm_core_savecontext)
107 ldmfd sp!, {r1-r7, r10, pc}
111 ENTRY_NP(arm_fpe_core_loadcontext)
112 stmfd sp!, {r0-r7, r10, lr}
115 bl _C_LABEL(fpe_arm_core_loadcontext)
116 ldmfd sp!, {r0-r7, r10, pc}
119 /* Only needs to preserve r10 */
121 ENTRY_NP(arm_fpe_core_activatecontext)
122 stmfd sp!, {r0-r7, r10, lr}
124 bl _C_LABEL(fpe_arm_core_activatecontext)
125 ldmfd sp!, {r0-r7, r10, pc}
127 /* Only needs to preserve r10 */
129 ENTRY_NP(arm_fpe_core_deactivatecontext)
130 stmfd sp!, {r1-r7, r10, lr}
131 bl _C_LABEL(fpe_arm_core_deactivatecontext)
132 ldmfd sp!, {r1-r7, r10, pc}
135 * Call back functions from the core
138 ENTRY_NP(arm_fpe_newhandler)
140 ldr r0, Llocal_handler_addr
145 .word _C_LABEL(undefined_handler_address)
147 ENTRY_NP(arm_fpe_restorehandler)
148 stmfd sp!, {r0-r1, lr}
149 ldr r0, Llocal_handler_addr
150 ldr r1, Lold_handler_addr
153 ldmfd sp!, {r0-r1, pc}
156 .word _C_LABEL(arm_fpe_old_handler_address)
158 ENTRY_NP(arm_fpe_handle_exception)
159 b _C_LABEL(arm_fpe_exception_glue)
161 ENTRY_NP(arm_fpe_get_ws)
164 ldr r0, Larm_fpe_core_workspace
170 Larm_fpe_core_workspace:
171 .word _C_LABEL(arm_fpe_core_workspace)
173 ENTRY_NP(arm_fpe_post_proc)
174 b _C_LABEL(arm_fpe_post_proc_glue)
177 /* Simple call back function that panics */
179 ENTRY_NP(arm_fpe_panic)
180 adr r0, Lfpe_panic_text
184 .asciz "armfpe: we are panicking"
188 * Call back routine from FPE on completion of an instruction
191 #ifdef CHECK_BEFORE_USERRET
193 .global _C_LABEL(userret_count0)
194 .global _C_LABEL(userret_count1)
196 _C_LABEL(userret_count0):
198 _C_LABEL(userret_count1):
204 .word _C_LABEL(userret_count0)
206 .word _C_LABEL(userret_count1)
209 .word _C_LABEL(want_resched)
212 .word _C_LABEL(curproc)
215 .word _C_LABEL(cpu_info_store)
219 ENTRY_NP(arm_fpe_post_proc_glue)
220 stmfd sp!, {r0-r3, lr}
222 #ifdef CHECK_BEFORE_USERRET
224 /* Call userret if we need a reschedule */
227 ldr r0, Luserret_count0
232 /* Do we need a reschedule */
233 ldr r0, Lwant_resched
238 /* All other userret requirement conditions come from curproc */
242 /* Remember the flags field */
243 ldr r3, [r0, #(P_FLAG)]
245 /* Get the signal list */
246 ldr r1, [r0, #(P_SIGLIST)]
248 beq Lno_signals_pending
253 ldr r1, [r0, #(P_SIGLIST)]
254 ldr r2, [r0, #(P_SIGMASK)]
260 /* Are we profiling ? */
264 /* Update the current priority */
265 ldrb r1, [r0, #(P_USRPRI)]
266 strb r1, [r0, #(P_PRIORITY)]
268 strb r1, [r0, #(CI_CURPRIORITY)]
271 ldmfd sp!, {r0-r3, pc}
274 /* Ok we need to call userret() */
276 stmfd sp!, {r4-r6, r10-r12}
279 ldr r0, Luserret_count1
286 /* This could be optimised as we are going from UND32->SVC32 mode */
289 bic r3, r4, #(PSR_MODE)
290 orr r3, r3, #(PSR_SVC32_MODE)
295 /* Reserve a trapframe on the SVC stack */
297 sub sp, sp, #(TRAPFRAMESIZE)
300 ldr r2, [r0, #-0x0008] /* Copy spsr */
301 str r2, [r1], #0x0004
303 ldmia r0!, {r2, r3, r5, r6} /* copy r0-r5 */
304 stmia r1!, {r2, r3, r5, r6}
306 ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
307 stmia r1!, {r2, r3, r5, r6}
309 ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
310 stmia r1!, {r2, r3, r5, r6}
312 ldmia r0!, {r2, r3, r5, r6} /* copy r12, r13, r14, r15 */
313 stmia r1!, {r2, r3, r5, r14}
314 str r6, [r1, #0x0000]
320 * OK Question Time ...
322 * Do I need to save SVC r14 ?
323 * It only needs saving if this routine can interrupt something already
324 * running in SVC mode. Since FP is only valid from USR32 mode this
331 /* More optimisation ... Need to code an assembly version of userret() */
333 bl _C_LABEL(arm_fpe_postproc)
335 /* Release the trapframe on the SVC stack */
340 ldr r2, [r0], #0x0004 /* Copy spsr */
341 str r2, [r6, #-0x0008]
343 ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r0-r5 */
344 stmia r6!, {r1, r2, r3, r5, r10, r11}
346 ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r6-r11 */
347 stmia r6!, {r1, r2, r3, r5, r10, r11}
349 ldmia r0!, {r1, r2, r3} /* copy r12, r13, r14 */
350 stmia r6!, {r1, r2, r3}
352 ldr r1, [r0, #0x0004]
355 add sp, sp, #(TRAPFRAMESIZE)
359 ldmfd sp!, {r4-r6, r10-r12}
360 ldmfd sp!, {r0-r3, pc}
364 * Call back routine from FPE when the an exception occurs
367 ENTRY_NP(arm_fpe_exception_glue)
368 stmfd sp!, {r0-r6, r10-r12, lr}
372 /* This could be optimised as we are going from UND32->SVC32 mode */
375 bic r3, r4, #(PSR_MODE)
376 orr r3, r3, #(PSR_SVC32_MODE)
381 /* Reserve a trapframe on the SVC stack */
383 sub sp, sp, #(TRAPFRAMESIZE)
386 ldr r2, [r0, #-0x0008] /* Copy spsr */
387 str r2, [r1], #0x0004
389 ldmia r0!, {r2, r3, r5, r6} /* copy r0-r5 */
390 stmia r1!, {r2, r3, r5, r6}
392 ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
393 stmia r1!, {r2, r3, r5, r6}
395 ldmia r0!, {r2, r3, r5, r6} /* copy r6-r11 */
396 stmia r1!, {r2, r3, r5, r6}
398 ldmia r0!, {r2, r3, r5, r6} /* copy r12, r13, r14, r15 */
399 stmia r1!, {r2, r3, r5, r14}
400 str r6, [r1, #0x0000]
402 mov r0, r10 /* exception */
403 mov r1, r12 /* fpframe */
404 mov r2, sp /* trapframe */
407 * OK Question Time ...
409 * Do I need to save SVC r14 ?
410 * It only needs saving if this routine can interrupt something already
411 * running in SVC mode. Since FP is only valid from USR32 mode this
418 /* More optimisation ... Need to code an assembly version of userret() */
420 bl _C_LABEL(arm_fpe_exception)
422 /* Release the trapframe on the SVC stack */
427 ldr r2, [r0], #0x0004 /* Copy spsr */
428 str r2, [r6, #-0x0008]
430 ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r0-r5 */
431 stmia r6!, {r1, r2, r3, r5, r10, r11}
433 ldmia r0!, {r1, r2, r3, r5, r10, r11} /* copy r6-r11 */
434 stmia r6!, {r1, r2, r3, r5, r10, r11}
436 ldmia r0!, {r1, r2, r3} /* copy r12, r13, r14 */
437 stmia r6!, {r1, r2, r3}
439 ldr r1, [r0, #0x0004]
442 add sp, sp, #(TRAPFRAMESIZE)
446 ldmfd sp!, {r0-r6, r10-r12, lr}
448 /* Now pull the original trapframe that the FPE pushed off the stack */
463 ENTRY_NP(arm_fpe_set_exception_mask)
464 rfs r1 /* Get FP status */
465 bic r1, r1, #0x001f0000 /* Zero exception mask */
466 and r0, r0, #0x0000001f /* Mask new bits */
467 orr r0, r1, r0, lsl #16 /* Merge */
468 wfs r0 /* Set status */
469 mov r0, r1, lsr #16 /* Return old mask */
470 mov pc, lr /* return */
473 .global _C_LABEL(fpe_nexthandler)
474 _C_LABEL(fpe_nexthandler):
475 .word _C_LABEL(undefinedinstruction_bounce)