Import 2.1.116pre2
[davej-history.git] / arch / m68k / fpsp040 / skeleton.S
blob1e4d0cf720accca4eb5e19269aa1b2c777ff6ad9
2 |       skeleton.sa 3.2 4/26/91
4 |       This file contains code that is system dependent and will
5 |       need to be modified to install the FPSP.
7 |       Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
8 |       Put any target system specific handling that must be done immediately
9 |       before the jump instruction.  If there no handling necessary, then
10 |       the 'fpsp_xxxx' handler entry point should be placed in the exception
11 |       table so that the 'jmp' can be eliminated. If the FPSP determines that the
12 |       exception is one that must be reported then there will be a
13 |       return from the package by a 'jmp real_xxxx'.  At that point
14 |       the machine state will be identical to the state before
15 |       the FPSP was entered.  In particular, whatever condition
16 |       that caused the exception will still be pending when the FPSP
17 |       package returns.  Thus, there will be system specific code
18 |       to handle the exception.
20 |       If the exception was completely handled by the package, then
21 |       the return will be via a 'jmp fpsp_done'.  Unless there is 
22 |       OS specific work to be done (such as handling a context switch or
23 |       interrupt) the user program can be resumed via 'rte'.
25 |       In the following skeleton code, some typical 'real_xxxx' handling
26 |       code is shown.  This code may need to be moved to an appropriate
27 |       place in the target system, or rewritten.
28 |       
30 |               Copyright (C) Motorola, Inc. 1990
31 |                       All Rights Reserved
33 |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
34 |       The copyright notice above does not evidence any  
35 |       actual or intended publication of such source code.
38 |       Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
41 #include <linux/linkage.h>
42 #include <asm/entry.h>
44 |SKELETON       idnt    2,1 | Motorola 040 Floating Point Software Package
46         |section 15
48 |       The following counters are used for standalone testing
51         |section 8
53         .include "fpsp.h"
55         |xref   b1238_fix
58 |       Divide by Zero exception
60 |       All dz exceptions are 'real', hence no fpsp_dz entry point.
62         .global dz
63         .global real_dz
64 dz:
65 real_dz:
66         link            %a6,#-LOCAL_SIZE
67         fsave           -(%sp)
68         bclrb           #E1,E_BYTE(%a6)
69         frestore        (%sp)+
70         unlk            %a6
72         SAVE_ALL_INT
73         GET_CURRENT(%d0)
74         movel   %sp,%sp@-               | stack frame pointer argument
75         bsrl    SYMBOL_NAME(trap_c)
76         addql   #4,%sp
77         bral    SYMBOL_NAME(ret_from_exception)
80 |       Inexact exception
82 |       All inexact exceptions are real, but the 'real' handler
83 |       will probably want to clear the pending exception.
84 |       The provided code will clear the E3 exception (if pending), 
85 |       otherwise clear the E1 exception.  The frestore is not really
86 |       necessary for E1 exceptions.
88 | Code following the 'inex' label is to handle bug #1232.  In this
89 | bug, if an E1 snan, ovfl, or unfl occurred, and the process was
90 | swapped out before taking the exception, the exception taken on
91 | return was inex, rather than the correct exception.  The snan, ovfl,
92 | and unfl exception to be taken must not have been enabled.  The
93 | fix is to check for E1, and the existence of one of snan, ovfl,
94 | or unfl bits set in the fpsr.  If any of these are set, branch
95 | to the appropriate  handler for the exception in the fpsr.  Note
96 | that this fix is only for d43b parts, and is skipped if the
97 | version number is not $40.
98
100         .global real_inex
101         .global inex
102 inex:
103         link            %a6,#-LOCAL_SIZE
104         fsave           -(%sp)
105         cmpib           #VER_40,(%sp)           |test version number
106         bnes            not_fmt40
107         fmovel          %fpsr,-(%sp)
108         btstb           #E1,E_BYTE(%a6)         |test for E1 set
109         beqs            not_b1232
110         btstb           #snan_bit,2(%sp) |test for snan
111         beq             inex_ckofl
112         addl            #4,%sp
113         frestore        (%sp)+
114         unlk            %a6
115         bra             snan
116 inex_ckofl:
117         btstb           #ovfl_bit,2(%sp) |test for ovfl
118         beq             inex_ckufl 
119         addl            #4,%sp
120         frestore        (%sp)+
121         unlk            %a6
122         bra             ovfl
123 inex_ckufl:
124         btstb           #unfl_bit,2(%sp) |test for unfl
125         beq             not_b1232
126         addl            #4,%sp
127         frestore        (%sp)+
128         unlk            %a6
129         bra             unfl
132 | We do not have the bug 1232 case.  Clean up the stack and call
133 | real_inex.
135 not_b1232:
136         addl            #4,%sp
137         frestore        (%sp)+
138         unlk            %a6
140 real_inex:
142         link            %a6,#-LOCAL_SIZE
143         fsave           -(%sp)
144 not_fmt40:
145         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
146         beqs            inex_cke1
148 | Clear dirty bit on dest resister in the frame before branching
149 | to b1238_fix.
151         moveml          %d0/%d1,USER_DA(%a6)
152         bfextu          CMDREG1B(%a6){#6:#3},%d0                |get dest reg no
153         bclrb           %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
154         bsrl            b1238_fix               |test for bug1238 case
155         moveml          USER_DA(%a6),%d0/%d1
156         bras            inex_done
157 inex_cke1:
158         bclrb           #E1,E_BYTE(%a6)
159 inex_done:
160         frestore        (%sp)+
161         unlk            %a6
163         SAVE_ALL_INT
164         GET_CURRENT(%d0)
165         movel   %sp,%sp@-               | stack frame pointer argument
166         bsrl    SYMBOL_NAME(trap_c)
167         addql   #4,%sp
168         bral    SYMBOL_NAME(ret_from_exception)
169         
171 |       Overflow exception
173         |xref   fpsp_ovfl
174         .global real_ovfl
175         .global ovfl
176 ovfl:
177         jmp     fpsp_ovfl
178 real_ovfl:
180         link            %a6,#-LOCAL_SIZE
181         fsave           -(%sp)
182         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
183         bnes            ovfl_done
184         bclrb           #E1,E_BYTE(%a6)
185 ovfl_done:
186         frestore        (%sp)+
187         unlk            %a6
189         SAVE_ALL_INT
190         GET_CURRENT(%d0)
191         movel   %sp,%sp@-               | stack frame pointer argument
192         bsrl    SYMBOL_NAME(trap_c)
193         addql   #4,%sp
194         bral    SYMBOL_NAME(ret_from_exception)
195         
197 |       Underflow exception
199         |xref   fpsp_unfl
200         .global real_unfl
201         .global unfl
202 unfl:
203         jmp     fpsp_unfl
204 real_unfl:
206         link            %a6,#-LOCAL_SIZE
207         fsave           -(%sp)
208         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
209         bnes            unfl_done
210         bclrb           #E1,E_BYTE(%a6)
211 unfl_done:
212         frestore        (%sp)+
213         unlk            %a6
215         SAVE_ALL_INT
216         GET_CURRENT(%d0)
217         movel   %sp,%sp@-               | stack frame pointer argument
218         bsrl    SYMBOL_NAME(trap_c)
219         addql   #4,%sp
220         bral    SYMBOL_NAME(ret_from_exception)
221         
223 |       Signalling NAN exception
225         |xref   fpsp_snan
226         .global real_snan
227         .global snan
228 snan:
229         jmp     fpsp_snan
230 real_snan:
231         link            %a6,#-LOCAL_SIZE
232         fsave           -(%sp)
233         bclrb           #E1,E_BYTE(%a6) |snan is always an E1 exception
234         frestore        (%sp)+
235         unlk            %a6
237         SAVE_ALL_INT
238         GET_CURRENT(%d0)
239         movel   %sp,%sp@-               | stack frame pointer argument
240         bsrl    SYMBOL_NAME(trap_c)
241         addql   #4,%sp
242         bral    SYMBOL_NAME(ret_from_exception)
243         
245 |       Operand Error exception
247         |xref   fpsp_operr
248         .global real_operr
249         .global operr
250 operr:
251         jmp     fpsp_operr
252 real_operr:
253         link            %a6,#-LOCAL_SIZE
254         fsave           -(%sp)
255         bclrb           #E1,E_BYTE(%a6) |operr is always an E1 exception
256         frestore        (%sp)+
257         unlk            %a6
259         SAVE_ALL_INT
260         GET_CURRENT(%d0)
261         movel   %sp,%sp@-               | stack frame pointer argument
262         bsrl    SYMBOL_NAME(trap_c)
263         addql   #4,%sp
264         bral    SYMBOL_NAME(ret_from_exception)
266         
268 |       BSUN exception
270 |       This sample handler simply clears the nan bit in the FPSR.
272         |xref   fpsp_bsun
273         .global real_bsun
274         .global bsun
275 bsun:
276         jmp     fpsp_bsun
277 real_bsun:
278         link            %a6,#-LOCAL_SIZE
279         fsave           -(%sp)
280         bclrb           #E1,E_BYTE(%a6) |bsun is always an E1 exception
281         fmovel          %FPSR,-(%sp)
282         bclrb           #nan_bit,(%sp)
283         fmovel          (%sp)+,%FPSR
284         frestore        (%sp)+
285         unlk            %a6
287         SAVE_ALL_INT
288         GET_CURRENT(%d0)
289         movel   %sp,%sp@-               | stack frame pointer argument
290         bsrl    SYMBOL_NAME(trap_c)
291         addql   #4,%sp
292         bral    SYMBOL_NAME(ret_from_exception)
295 |       F-line exception
297 |       A 'real' F-line exception is one that the FPSP isn't supposed to 
298 |       handle. E.g. an instruction with a co-processor ID that is not 1.
301         |xref   fpsp_fline
302         .global real_fline
303         .global fline
304 fline:
305         jmp     fpsp_fline
306 real_fline:
308         SAVE_ALL_INT
309         GET_CURRENT(%d0)
310         movel   %sp,%sp@-               | stack frame pointer argument
311         bsrl    SYMBOL_NAME(trap_c)
312         addql   #4,%sp
313         bral    SYMBOL_NAME(ret_from_exception)
316 |       Unsupported data type exception
318         |xref   fpsp_unsupp
319         .global real_unsupp
320         .global unsupp
321 unsupp:
322         jmp     fpsp_unsupp
323 real_unsupp:
324         link            %a6,#-LOCAL_SIZE
325         fsave           -(%sp)
326         bclrb           #E1,E_BYTE(%a6) |unsupp is always an E1 exception
327         frestore        (%sp)+
328         unlk            %a6
330         SAVE_ALL_INT
331         GET_CURRENT(%d0)
332         movel   %sp,%sp@-               | stack frame pointer argument
333         bsrl    SYMBOL_NAME(trap_c)
334         addql   #4,%sp
335         bral    SYMBOL_NAME(ret_from_exception)
338 |       Trace exception
340         .global real_trace
341 real_trace:
342         |
343         bral    SYMBOL_NAME(trap)
346 |       fpsp_fmt_error --- exit point for frame format error
348 |       The fpu stack frame does not match the frames existing
349 |       or planned at the time of this writing.  The fpsp is
350 |       unable to handle frame sizes not in the following
351 |       version:size pairs:
353 |       {4060, 4160} - busy frame
354 |       {4028, 4130} - unimp frame
355 |       {4000, 4100} - idle frame
357 |       This entry point simply holds an f-line illegal value.  
358 |       Replace this with a call to your kernel panic code or
359 |       code to handle future revisions of the fpu.
361         .global fpsp_fmt_error
362 fpsp_fmt_error:
364         .long   0xf27f0000      |f-line illegal 
367 |       fpsp_done --- FPSP exit point
369 |       The exception has been handled by the package and we are ready
370 |       to return to user mode, but there may be OS specific code
371 |       to execute before we do.  If there is, do it now.
375         .global fpsp_done
376 fpsp_done:
377         btst    #0x5,%sp@               | supervisor bit set in saved SR?
378         beq     Lnotkern
379         rte
380 Lnotkern:
381         SAVE_ALL_INT
382         GET_CURRENT(%d0)
383         tstl    %curptr@(LTASK_NEEDRESCHED)
384         jne     SYMBOL_NAME(ret_from_exception) | deliver signals,
385                                                 | reschedule etc..
386         RESTORE_ALL
389 |       mem_write --- write to user or supervisor address space
391 | Writes to memory while in supervisor mode.  copyout accomplishes
392 | this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
393 | If you don't have copyout, use the local copy of the function below.
395 |       a0 - supervisor source address
396 |       a1 - user destination address
397 |       d0 - number of bytes to write (maximum count is 12)
399 | The supervisor source address is guaranteed to point into the supervisor
400 | stack.  The result is that a UNIX
401 | process is allowed to sleep as a consequence of a page fault during
402 | copyout.  The probability of a page fault is exceedingly small because
403 | the 68040 always reads the destination address and thus the page
404 | faults should have already been handled.
406 | If the EXC_SR shows that the exception was from supervisor space,
407 | then just do a dumb (and slow) memory move.  In a UNIX environment
408 | there shouldn't be any supervisor mode floating point exceptions.
410         .global mem_write
411 mem_write:
412         btstb   #5,EXC_SR(%a6)  |check for supervisor state
413         beqs    user_write
414 super_write:
415         moveb   (%a0)+,(%a1)+
416         subql   #1,%d0
417         bnes    super_write
418         rts
419 user_write:
420         movel   %d1,-(%sp)      |preserve d1 just in case
421         movel   %d0,-(%sp)
422         movel   %a1,-(%sp)
423         movel   %a0,-(%sp)
424         jsr             copyout
425         addw    #12,%sp
426         movel   (%sp)+,%d1
427         rts
429 |       mem_read --- read from user or supervisor address space
431 | Reads from memory while in supervisor mode.  copyin accomplishes
432 | this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
433 | If you don't have copyin, use the local copy of the function below.
435 | The FPSP calls mem_read to read the original F-line instruction in order
436 | to extract the data register number when the 'Dn' addressing mode is
437 | used.
439 |Input:
440 |       a0 - user source address
441 |       a1 - supervisor destination address
442 |       d0 - number of bytes to read (maximum count is 12)
444 | Like mem_write, mem_read always reads with a supervisor 
445 | destination address on the supervisor stack.  Also like mem_write,
446 | the EXC_SR is checked and a simple memory copy is done if reading
447 | from supervisor space is indicated.
449         .global mem_read
450 mem_read:
451         btstb   #5,EXC_SR(%a6)  |check for supervisor state
452         beqs    user_read
453 super_read:
454         moveb   (%a0)+,(%a1)+
455         subql   #1,%d0
456         bnes    super_read
457         rts
458 user_read:
459         movel   %d1,-(%sp)      |preserve d1 just in case
460         movel   %d0,-(%sp)
461         movel   %a1,-(%sp)
462         movel   %a0,-(%sp)
463         jsr     copyin
464         addw    #12,%sp
465         movel   (%sp)+,%d1
466         rts
469 | Use these routines if your kernel doesn't have copyout/copyin equivalents.
470 | Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
471 | and copyin overwrites SFC.
473 copyout:
474         movel   4(%sp),%a0      | source
475         movel   8(%sp),%a1      | destination
476         movel   12(%sp),%d0     | count
477         subl    #1,%d0          | dec count by 1 for dbra
478         movel   #1,%d1
480 |       DFC is already set
481 |       movec   %d1,%DFC                | set dfc for user data space
482 moreout:
483         moveb   (%a0)+,%d1      | fetch supervisor byte
484 out_ea:
485         movesb  %d1,(%a1)+      | write user byte
486         dbf     %d0,moreout
487         rts
489 copyin:
490         movel   4(%sp),%a0      | source
491         movel   8(%sp),%a1      | destination
492         movel   12(%sp),%d0     | count
493         subl    #1,%d0          | dec count by 1 for dbra
494         movel   #1,%d1
495 |       SFC is already set
496 |       movec   %d1,%SFC                | set sfc for user space
497 morein:
498 in_ea:
499         movesb  (%a0)+,%d1      | fetch user byte
500         moveb   %d1,(%a1)+      | write supervisor byte
501         dbf     %d0,morein
502         rts
504         .section .fixup,#alloc,#execinstr
505         .even
507         jbra    SYMBOL_NAME(fpsp040_die)
509         .section __ex_table,#alloc
510         .align  4
512         .long   in_ea,1b
513         .long   out_ea,1b
515         |end