Back to home page

LXR

 
 

    


0001 |
0002 |   skeleton.sa 3.2 4/26/91
0003 |
0004 |   This file contains code that is system dependent and will
0005 |   need to be modified to install the FPSP.
0006 |
0007 |   Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
0008 |   Put any target system specific handling that must be done immediately
0009 |   before the jump instruction.  If there no handling necessary, then
0010 |   the 'fpsp_xxxx' handler entry point should be placed in the exception
0011 |   table so that the 'jmp' can be eliminated. If the FPSP determines that the
0012 |   exception is one that must be reported then there will be a
0013 |   return from the package by a 'jmp real_xxxx'.  At that point
0014 |   the machine state will be identical to the state before
0015 |   the FPSP was entered.  In particular, whatever condition
0016 |   that caused the exception will still be pending when the FPSP
0017 |   package returns.  Thus, there will be system specific code
0018 |   to handle the exception.
0019 |
0020 |   If the exception was completely handled by the package, then
0021 |   the return will be via a 'jmp fpsp_done'.  Unless there is
0022 |   OS specific work to be done (such as handling a context switch or
0023 |   interrupt) the user program can be resumed via 'rte'.
0024 |
0025 |   In the following skeleton code, some typical 'real_xxxx' handling
0026 |   code is shown.  This code may need to be moved to an appropriate
0027 |   place in the target system, or rewritten.
0028 |
0029 
0030 |       Copyright (C) Motorola, Inc. 1990
0031 |           All Rights Reserved
0032 |
0033 |       For details on the license for this file, please see the
0034 |       file, README, in this same directory.
0035 
0036 |
0037 |   Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
0038 |
0039 
0040 #include <linux/linkage.h>
0041 #include <asm/entry.h>
0042 #include <asm/asm-offsets.h>
0043 
0044 |SKELETON   idnt    2,1 | Motorola 040 Floating Point Software Package
0045 
0046     |section 15
0047 |
0048 |   The following counters are used for standalone testing
0049 |
0050 
0051     |section 8
0052 
0053 #include "fpsp.h"
0054 
0055     |xref   b1238_fix
0056 
0057 |
0058 |   Divide by Zero exception
0059 |
0060 |   All dz exceptions are 'real', hence no fpsp_dz entry point.
0061 |
0062     .global dz
0063     .global real_dz
0064 dz:
0065 real_dz:
0066     link        %a6,#-LOCAL_SIZE
0067     fsave       -(%sp)
0068     bclrb       #E1,E_BYTE(%a6)
0069     frestore    (%sp)+
0070     unlk        %a6
0071 
0072     SAVE_ALL_INT
0073     GET_CURRENT(%d0)
0074     movel   %sp,%sp@-       | stack frame pointer argument
0075     bsrl    trap_c
0076     addql   #4,%sp
0077     bral    ret_from_exception
0078 
0079 |
0080 |   Inexact exception
0081 |
0082 |   All inexact exceptions are real, but the 'real' handler
0083 |   will probably want to clear the pending exception.
0084 |   The provided code will clear the E3 exception (if pending),
0085 |   otherwise clear the E1 exception.  The frestore is not really
0086 |   necessary for E1 exceptions.
0087 |
0088 | Code following the 'inex' label is to handle bug #1232.  In this
0089 | bug, if an E1 snan, ovfl, or unfl occurred, and the process was
0090 | swapped out before taking the exception, the exception taken on
0091 | return was inex, rather than the correct exception.  The snan, ovfl,
0092 | and unfl exception to be taken must not have been enabled.  The
0093 | fix is to check for E1, and the existence of one of snan, ovfl,
0094 | or unfl bits set in the fpsr.  If any of these are set, branch
0095 | to the appropriate  handler for the exception in the fpsr.  Note
0096 | that this fix is only for d43b parts, and is skipped if the
0097 | version number is not $40.
0098 |
0099 |
0100     .global real_inex
0101     .global inex
0102 inex:
0103     link        %a6,#-LOCAL_SIZE
0104     fsave       -(%sp)
0105     cmpib       #VER_40,(%sp)       |test version number
0106     bnes        not_fmt40
0107     fmovel      %fpsr,-(%sp)
0108     btstb       #E1,E_BYTE(%a6)     |test for E1 set
0109     beqs        not_b1232
0110     btstb       #snan_bit,2(%sp) |test for snan
0111     beq     inex_ckofl
0112     addl        #4,%sp
0113     frestore    (%sp)+
0114     unlk        %a6
0115     bra     snan
0116 inex_ckofl:
0117     btstb       #ovfl_bit,2(%sp) |test for ovfl
0118     beq     inex_ckufl
0119     addl        #4,%sp
0120     frestore    (%sp)+
0121     unlk        %a6
0122     bra     ovfl
0123 inex_ckufl:
0124     btstb       #unfl_bit,2(%sp) |test for unfl
0125     beq     not_b1232
0126     addl        #4,%sp
0127     frestore    (%sp)+
0128     unlk        %a6
0129     bra     unfl
0130 
0131 |
0132 | We do not have the bug 1232 case.  Clean up the stack and call
0133 | real_inex.
0134 |
0135 not_b1232:
0136     addl        #4,%sp
0137     frestore    (%sp)+
0138     unlk        %a6
0139 
0140 real_inex:
0141 
0142     link        %a6,#-LOCAL_SIZE
0143     fsave       -(%sp)
0144 not_fmt40:
0145     bclrb       #E3,E_BYTE(%a6)     |clear and test E3 flag
0146     beqs        inex_cke1
0147 |
0148 | Clear dirty bit on dest resister in the frame before branching
0149 | to b1238_fix.
0150 |
0151     moveml      %d0/%d1,USER_DA(%a6)
0152     bfextu      CMDREG1B(%a6){#6:#3},%d0        |get dest reg no
0153     bclrb       %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
0154     bsrl        b1238_fix       |test for bug1238 case
0155     moveml      USER_DA(%a6),%d0/%d1
0156     bras        inex_done
0157 inex_cke1:
0158     bclrb       #E1,E_BYTE(%a6)
0159 inex_done:
0160     frestore    (%sp)+
0161     unlk        %a6
0162 
0163     SAVE_ALL_INT
0164     GET_CURRENT(%d0)
0165     movel   %sp,%sp@-       | stack frame pointer argument
0166     bsrl    trap_c
0167     addql   #4,%sp
0168     bral    ret_from_exception
0169 
0170 |
0171 |   Overflow exception
0172 |
0173     |xref   fpsp_ovfl
0174     .global real_ovfl
0175     .global ovfl
0176 ovfl:
0177     jmp fpsp_ovfl
0178 real_ovfl:
0179 
0180     link        %a6,#-LOCAL_SIZE
0181     fsave       -(%sp)
0182     bclrb       #E3,E_BYTE(%a6)     |clear and test E3 flag
0183     bnes        ovfl_done
0184     bclrb       #E1,E_BYTE(%a6)
0185 ovfl_done:
0186     frestore    (%sp)+
0187     unlk        %a6
0188 
0189     SAVE_ALL_INT
0190     GET_CURRENT(%d0)
0191     movel   %sp,%sp@-       | stack frame pointer argument
0192     bsrl    trap_c
0193     addql   #4,%sp
0194     bral    ret_from_exception
0195 
0196 |
0197 |   Underflow exception
0198 |
0199     |xref   fpsp_unfl
0200     .global real_unfl
0201     .global unfl
0202 unfl:
0203     jmp fpsp_unfl
0204 real_unfl:
0205 
0206     link        %a6,#-LOCAL_SIZE
0207     fsave       -(%sp)
0208     bclrb       #E3,E_BYTE(%a6)     |clear and test E3 flag
0209     bnes        unfl_done
0210     bclrb       #E1,E_BYTE(%a6)
0211 unfl_done:
0212     frestore    (%sp)+
0213     unlk        %a6
0214 
0215     SAVE_ALL_INT
0216     GET_CURRENT(%d0)
0217     movel   %sp,%sp@-       | stack frame pointer argument
0218     bsrl    trap_c
0219     addql   #4,%sp
0220     bral    ret_from_exception
0221 
0222 |
0223 |   Signalling NAN exception
0224 |
0225     |xref   fpsp_snan
0226     .global real_snan
0227     .global snan
0228 snan:
0229     jmp fpsp_snan
0230 real_snan:
0231     link        %a6,#-LOCAL_SIZE
0232     fsave       -(%sp)
0233     bclrb       #E1,E_BYTE(%a6) |snan is always an E1 exception
0234     frestore    (%sp)+
0235     unlk        %a6
0236 
0237     SAVE_ALL_INT
0238     GET_CURRENT(%d0)
0239     movel   %sp,%sp@-       | stack frame pointer argument
0240     bsrl    trap_c
0241     addql   #4,%sp
0242     bral    ret_from_exception
0243 
0244 |
0245 |   Operand Error exception
0246 |
0247     |xref   fpsp_operr
0248     .global real_operr
0249     .global operr
0250 operr:
0251     jmp fpsp_operr
0252 real_operr:
0253     link        %a6,#-LOCAL_SIZE
0254     fsave       -(%sp)
0255     bclrb       #E1,E_BYTE(%a6) |operr is always an E1 exception
0256     frestore    (%sp)+
0257     unlk        %a6
0258 
0259     SAVE_ALL_INT
0260     GET_CURRENT(%d0)
0261     movel   %sp,%sp@-       | stack frame pointer argument
0262     bsrl    trap_c
0263     addql   #4,%sp
0264     bral    ret_from_exception
0265 
0266 
0267 |
0268 |   BSUN exception
0269 |
0270 |   This sample handler simply clears the nan bit in the FPSR.
0271 |
0272     |xref   fpsp_bsun
0273     .global real_bsun
0274     .global bsun
0275 bsun:
0276     jmp fpsp_bsun
0277 real_bsun:
0278     link        %a6,#-LOCAL_SIZE
0279     fsave       -(%sp)
0280     bclrb       #E1,E_BYTE(%a6) |bsun is always an E1 exception
0281     fmovel      %FPSR,-(%sp)
0282     bclrb       #nan_bit,(%sp)
0283     fmovel      (%sp)+,%FPSR
0284     frestore    (%sp)+
0285     unlk        %a6
0286 
0287     SAVE_ALL_INT
0288     GET_CURRENT(%d0)
0289     movel   %sp,%sp@-       | stack frame pointer argument
0290     bsrl    trap_c
0291     addql   #4,%sp
0292     bral    ret_from_exception
0293 
0294 |
0295 |   F-line exception
0296 |
0297 |   A 'real' F-line exception is one that the FPSP isn't supposed to
0298 |   handle. E.g. an instruction with a co-processor ID that is not 1.
0299 |
0300 |
0301     |xref   fpsp_fline
0302     .global real_fline
0303     .global fline
0304 fline:
0305     jmp fpsp_fline
0306 real_fline:
0307 
0308     SAVE_ALL_INT
0309     GET_CURRENT(%d0)
0310     movel   %sp,%sp@-       | stack frame pointer argument
0311     bsrl    trap_c
0312     addql   #4,%sp
0313     bral    ret_from_exception
0314 
0315 |
0316 |   Unsupported data type exception
0317 |
0318     |xref   fpsp_unsupp
0319     .global real_unsupp
0320     .global unsupp
0321 unsupp:
0322     jmp fpsp_unsupp
0323 real_unsupp:
0324     link        %a6,#-LOCAL_SIZE
0325     fsave       -(%sp)
0326     bclrb       #E1,E_BYTE(%a6) |unsupp is always an E1 exception
0327     frestore    (%sp)+
0328     unlk        %a6
0329 
0330     SAVE_ALL_INT
0331     GET_CURRENT(%d0)
0332     movel   %sp,%sp@-       | stack frame pointer argument
0333     bsrl    trap_c
0334     addql   #4,%sp
0335     bral    ret_from_exception
0336 
0337 |
0338 |   Trace exception
0339 |
0340     .global real_trace
0341 real_trace:
0342     |
0343     bral    trap
0344 
0345 |
0346 |   fpsp_fmt_error --- exit point for frame format error
0347 |
0348 |   The fpu stack frame does not match the frames existing
0349 |   or planned at the time of this writing.  The fpsp is
0350 |   unable to handle frame sizes not in the following
0351 |   version:size pairs:
0352 |
0353 |   {4060, 4160} - busy frame
0354 |   {4028, 4130} - unimp frame
0355 |   {4000, 4100} - idle frame
0356 |
0357 |   This entry point simply holds an f-line illegal value.
0358 |   Replace this with a call to your kernel panic code or
0359 |   code to handle future revisions of the fpu.
0360 |
0361     .global fpsp_fmt_error
0362 fpsp_fmt_error:
0363 
0364     .long   0xf27f0000  |f-line illegal
0365 
0366 |
0367 |   fpsp_done --- FPSP exit point
0368 |
0369 |   The exception has been handled by the package and we are ready
0370 |   to return to user mode, but there may be OS specific code
0371 |   to execute before we do.  If there is, do it now.
0372 |
0373 |
0374 
0375     .global fpsp_done
0376 fpsp_done:
0377     btst    #0x5,%sp@       | supervisor bit set in saved SR?
0378     beq .Lnotkern
0379     rte
0380 .Lnotkern:
0381     SAVE_ALL_INT
0382     GET_CURRENT(%d0)
0383     | deliver signals, reschedule etc..
0384     jra ret_from_exception
0385 
0386 |
0387 |   mem_write --- write to user or supervisor address space
0388 |
0389 | Writes to memory while in supervisor mode.  copyout accomplishes
0390 | this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
0391 | If you don't have copyout, use the local copy of the function below.
0392 |
0393 |   a0 - supervisor source address
0394 |   a1 - user destination address
0395 |   d0 - number of bytes to write (maximum count is 12)
0396 |
0397 | The supervisor source address is guaranteed to point into the supervisor
0398 | stack.  The result is that a UNIX
0399 | process is allowed to sleep as a consequence of a page fault during
0400 | copyout.  The probability of a page fault is exceedingly small because
0401 | the 68040 always reads the destination address and thus the page
0402 | faults should have already been handled.
0403 |
0404 | If the EXC_SR shows that the exception was from supervisor space,
0405 | then just do a dumb (and slow) memory move.  In a UNIX environment
0406 | there shouldn't be any supervisor mode floating point exceptions.
0407 |
0408     .global mem_write
0409 mem_write:
0410     btstb   #5,EXC_SR(%a6)  |check for supervisor state
0411     beqs    user_write
0412 super_write:
0413     moveb   (%a0)+,(%a1)+
0414     subql   #1,%d0
0415     bnes    super_write
0416     rts
0417 user_write:
0418     movel   %d1,-(%sp)  |preserve d1 just in case
0419     movel   %d0,-(%sp)
0420     movel   %a1,-(%sp)
0421     movel   %a0,-(%sp)
0422     jsr     copyout
0423     addw    #12,%sp
0424     movel   (%sp)+,%d1
0425     rts
0426 |
0427 |   mem_read --- read from user or supervisor address space
0428 |
0429 | Reads from memory while in supervisor mode.  copyin accomplishes
0430 | this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
0431 | If you don't have copyin, use the local copy of the function below.
0432 |
0433 | The FPSP calls mem_read to read the original F-line instruction in order
0434 | to extract the data register number when the 'Dn' addressing mode is
0435 | used.
0436 |
0437 |Input:
0438 |   a0 - user source address
0439 |   a1 - supervisor destination address
0440 |   d0 - number of bytes to read (maximum count is 12)
0441 |
0442 | Like mem_write, mem_read always reads with a supervisor
0443 | destination address on the supervisor stack.  Also like mem_write,
0444 | the EXC_SR is checked and a simple memory copy is done if reading
0445 | from supervisor space is indicated.
0446 |
0447     .global mem_read
0448 mem_read:
0449     btstb   #5,EXC_SR(%a6)  |check for supervisor state
0450     beqs    user_read
0451 super_read:
0452     moveb   (%a0)+,(%a1)+
0453     subql   #1,%d0
0454     bnes    super_read
0455     rts
0456 user_read:
0457     movel   %d1,-(%sp)  |preserve d1 just in case
0458     movel   %d0,-(%sp)
0459     movel   %a1,-(%sp)
0460     movel   %a0,-(%sp)
0461     jsr copyin
0462     addw    #12,%sp
0463     movel   (%sp)+,%d1
0464     rts
0465 
0466 |
0467 | Use these routines if your kernel doesn't have copyout/copyin equivalents.
0468 | Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
0469 | and copyin overwrites SFC.
0470 |
0471 copyout:
0472     movel   4(%sp),%a0  | source
0473     movel   8(%sp),%a1  | destination
0474     movel   12(%sp),%d0 | count
0475     subl    #1,%d0      | dec count by 1 for dbra
0476     movel   #1,%d1
0477 
0478 |   DFC is already set
0479 |   movec   %d1,%DFC        | set dfc for user data space
0480 moreout:
0481     moveb   (%a0)+,%d1  | fetch supervisor byte
0482 out_ea:
0483     movesb  %d1,(%a1)+  | write user byte
0484     dbf %d0,moreout
0485     rts
0486 
0487 copyin:
0488     movel   4(%sp),%a0  | source
0489     movel   8(%sp),%a1  | destination
0490     movel   12(%sp),%d0 | count
0491     subl    #1,%d0      | dec count by 1 for dbra
0492     movel   #1,%d1
0493 |   SFC is already set
0494 |   movec   %d1,%SFC        | set sfc for user space
0495 morein:
0496 in_ea:
0497     movesb  (%a0)+,%d1  | fetch user byte
0498     moveb   %d1,(%a1)+  | write supervisor byte
0499     dbf %d0,morein
0500     rts
0501 
0502     .section .fixup,#alloc,#execinstr
0503     .even
0504 1:
0505     jbra    fpsp040_die
0506 
0507     .section __ex_table,#alloc
0508     .align  4
0509 
0510     .long   in_ea,1b
0511     .long   out_ea,1b
0512 
0513     |end