Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / arm / fpe-arm / armfpe_glue.S
blobfdb8c099d5bf89b28825470d48bfc389404d571f
1 /*      $NetBSD: armfpe_glue.S,v 1.2.22.3 2004/09/21 13:13:19 skrll Exp $       */
3 /*
4  * Copyright (c) 1996 Mark Brinicombe
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
21  *
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
32  * SUCH DAMAGE.
33  *
34  * RiscBSD kernel project
35  *
36  * arm_fpe_glue.S
37  *
38  * Glue code for calling the ARM FPE core code
39  *
40  * Created      : 21/12/95
41  */
43 #define CHECK_BEFORE_USERRET
44 #include "assym.h"
45 #include <machine/asm.h>
46 #include <machine/cpu.h>
49  * Glue for calling the core entry points
50  */
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)
63         stmfd   sp!, {r10, lr}
64         mov     r10, r0
65         bl      _C_LABEL(fpe_arm_core_initws)
66         ldmfd   sp!, {r10, pc}
68 ENTRY_NP(arm_fpe_core_abort)
69         stmfd   sp!, {r1-r7, r10, lr}
70         mov     r10, r0
71         mov     r0, r1
72         mov     r1, r2
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}
80         mov     r10, r0
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}
88         mov     r10, r0
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}
99 /* Preserve r10 */
101 ENTRY_NP(arm_fpe_core_savecontext)
102         stmfd   sp!, {r1-r7, r10, lr}
103         mov     r10, r0
104         mov     r0, r1
105         mov     r1, r2
106         bl      _C_LABEL(fpe_arm_core_savecontext)
107         ldmfd   sp!, {r1-r7, r10, pc}
109 /* Preserve r10 */
111 ENTRY_NP(arm_fpe_core_loadcontext)
112         stmfd   sp!, {r0-r7, r10, lr}
113         mov     r10, r0
114         mov     r0, r1
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}
123         mov     r10, r0
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
136  */
138 ENTRY_NP(arm_fpe_newhandler)
139         stmfd   sp!, {r0, lr}
140         ldr     r0, Llocal_handler_addr
141         str     r1, [r0]
142         ldmfd   sp!, {r0, pc}
144 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
151         ldr     r1, [r1]
152         str     r1, [r0]
153         ldmfd   sp!, {r0-r1, pc}
155 Lold_handler_addr:
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)
162         sub     sp, sp, #8
163         str     r0, [sp]
164         ldr     r0, Larm_fpe_core_workspace
165         ldr     r0, [r0]
166         str     r0, [sp, #4]
167         ldr     r0, [sp], #4
168         mov     pc, lr
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
181         b       _C_LABEL(panic)
183 Lfpe_panic_text:
184         .asciz  "armfpe: we are panicking"
185         .align  0
188  * Call back routine from FPE on completion of an instruction
189  */
191 #ifdef CHECK_BEFORE_USERRET
193         .global _C_LABEL(userret_count0)
194         .global _C_LABEL(userret_count1)
195         .data
196 _C_LABEL(userret_count0):
197         .word   0
198 _C_LABEL(userret_count1):
199         .word   0
201         .text
203 Luserret_count0:
204         .word   _C_LABEL(userret_count0)
205 Luserret_count1:
206         .word   _C_LABEL(userret_count1)
208 Lwant_resched:
209         .word   _C_LABEL(want_resched)
211 Lcurproc:
212         .word   _C_LABEL(curproc)
214 Lcurpriority:
215         .word   _C_LABEL(cpu_info_store)
217 #endif
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 */
226         /* Debugging */
227         ldr     r0, Luserret_count0
228         ldr     r1, [r0]
229         add     r1, r1, #1
230         str     r1, [r0]
232         /* Do we need a reschedule */
233         ldr     r0, Lwant_resched
234         ldr     r0, [r0]
235         teq     r0, #0x00000000
236         bne     Lwe_need_userret
238         /* All other userret requirement conditions come from curproc */
239         ldr     r0, Lcurproc
240         ldr     r0, [r0]
242         /* Remember the flags field */
243         ldr     r3, [r0, #(P_FLAG)]
245         /* Get the signal list */
246         ldr     r1, [r0, #(P_SIGLIST)]
247         teq     r1, #0x00000000
248         beq     Lno_signals_pending
250         tst     r3, #(P_TRACED)
251         bne     Lwe_need_userret
253         ldr     r1, [r0, #(P_SIGLIST)]
254         ldr     r2, [r0, #(P_SIGMASK)]
255         bic     r1, r1, r2
256         teq     r1, #0x00000000
257         bne     Lwe_need_userret
259 Lno_signals_pending:
260         /* Are we profiling ? */
261         tst     r3, #(P_PROFIL)
262         bne     Lwe_need_userret
264         /* Update the current priority */
265         ldrb    r1, [r0, #(P_USRPRI)]
266         strb    r1, [r0, #(P_PRIORITY)]
267         ldr     r0, Lcurpriority
268         strb    r1, [r0, #(CI_CURPRIORITY)]
270         /* Fast return */
271         ldmfd   sp!, {r0-r3, pc}
273 Lwe_need_userret:
274         /* Ok we need to call userret() */
276         stmfd   sp!, {r4-r6, r10-r12}
278         /* Debugging */
279         ldr     r0, Luserret_count1
280         ldr     r1, [r0]
281         add     r1, r1, #1
282         str     r1, [r0]
284 #endif
286 /* This could be optimised as we are going from UND32->SVC32 mode */
288         mrs     r4, cpsr_all
289         bic     r3, r4, #(PSR_MODE)
290         orr     r3, r3, #(PSR_SVC32_MODE)
291         msr     cpsr_all, r3
293         mov     r0, r12
295 /* Reserve a trapframe on the SVC stack */
297         sub     sp, sp, #(TRAPFRAMESIZE)
298         mov     r1, sp
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]
316         mov     r0, r12
317         mov     r1, sp
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
325  * should not happen.
326  */
328         mov     r5, r14
329         mov     r6, r12
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 */
336         mov     r14, r5
338         mov     r0, sp
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]
353         str     r1, [r6]
355         add     sp, sp, #(TRAPFRAMESIZE)
357         msr     cpsr_all, r4
359         ldmfd   sp!, {r4-r6, r10-r12}
360         ldmfd   sp!, {r0-r3, pc}
364  * Call back routine from FPE when the an exception occurs
365  */
367 ENTRY_NP(arm_fpe_exception_glue)
368         stmfd   sp!, {r0-r6, r10-r12, lr}
370         mov     r10, r0
372 /* This could be optimised as we are going from UND32->SVC32 mode */
374         mrs     r4, cpsr_all
375         bic     r3, r4, #(PSR_MODE)
376         orr     r3, r3, #(PSR_SVC32_MODE)
377         msr     cpsr_all, r3
379         mov     r0, r12
381 /* Reserve a trapframe on the SVC stack */
383         sub     sp, sp, #(TRAPFRAMESIZE)
384         mov     r1, sp
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
412  * should not happen.
413  */
415         mov     r5, r14
416         mov     r6, r12
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 */
423         mov     r14, r5
425         mov     r0, sp
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]
440         str     r1, [r6]
442         add     sp, sp, #(TRAPFRAMESIZE)
444         msr     cpsr_all, r4
446         ldmfd   sp!, {r0-r6, r10-r12, lr}
448 /* Now pull the original trapframe that the FPE pushed off the stack */
450         ldmdb   r12, {r0, r1}
452         msr     cpsr_all, r1
453         msr     spsr_all, r0
455         mov     sp, r12
457         ldmia   sp, {r0-r14}^
458         mov     r0, r0
459         add     sp, sp, #15*4
460         ldmfd   sp!, {pc}^
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)