OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [fpsp040/] [skeleton.S] - Rev 1765

Compare with Previous | Blame | View Log

|
|       skeleton.sa 3.2 4/26/91
|
|       This file contains code that is system dependent and will
|       need to be modified to install the FPSP.
|
|       Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
|       Put any target system specific handling that must be done immediately
|       before the jump instruction.  If there no handling necessary, then
|       the 'fpsp_xxxx' handler entry point should be placed in the exception
|       table so that the 'jmp' can be eliminated. If the FPSP determines that the
|       exception is one that must be reported then there will be a
|       return from the package by a 'jmp real_xxxx'.  At that point
|       the machine state will be identical to the state before
|       the FPSP was entered.  In particular, whatever condition
|       that caused the exception will still be pending when the FPSP
|       package returns.  Thus, there will be system specific code
|       to handle the exception.
|
|       If the exception was completely handled by the package, then
|       the return will be via a 'jmp fpsp_done'.  Unless there is 
|       OS specific work to be done (such as handling a context switch or
|       interrupt) the user program can be resumed via 'rte'.
|
|       In the following skeleton code, some typical 'real_xxxx' handling
|       code is shown.  This code may need to be moved to an appropriate
|       place in the target system, or rewritten.
|       

|               Copyright (C) Motorola, Inc. 1990
|                       All Rights Reserved
|
|       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
|       The copyright notice above does not evidence any  
|       actual or intended publication of such source code.

|
|       Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
|

#include <linux/linkage.h>

|SKELETON       idnt    2,1 | Motorola 040 Floating Point Software Package

        |section 15
|
|       The following counters are used for standalone testing
|
sigunimp:       .long   0
sigbsun:                .long   0
siginex:                .long   0
sigdz:          .long   0
sigunfl:                .long   0
sigovfl:                .long   0
sigoperr:       .long   0
sigsnan:                .long   0
sigunsupp:      .long   0

        |section 8
 
        .include "fpsp.h"

LOFF_ORIG_D0    = 0x20

#define SAVE_ALL                                \
        clrl    %sp@-;     /* stk_adj */        \
        movel   %d0,%sp@-; /* orig d0 */        \
        movel   %d0,%sp@-; /* d0 */             \
        moveml  %d1-%d5/%a0-%a1,%sp@-

        |xref   b1238_fix

|
|       Divide by Zero exception
|
|       All dz exceptions are 'real', hence no fpsp_dz entry point.
|
        .global dz
        .global real_dz
dz:
real_dz:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E1,E_BYTE(%a6)
        frestore        (%sp)+
        unlk            %a6

        addl    #1,sigdz                |for standalone testing

        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)

|
|       Inexact exception
|
|       All inexact exceptions are real, but the 'real' handler
|       will probably want to clear the pending exception.
|       The provided code will clear the E3 exception (if pending), 
|       otherwise clear the E1 exception.  The frestore is not really
|       necessary for E1 exceptions.
|
| Code following the 'inex' label is to handle bug #1232.  In this
| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
| swapped out before taking the exception, the exception taken on
| return was inex, rather than the correct exception.  The snan, ovfl,
| and unfl exception to be taken must not have been enabled.  The
| fix is to check for E1, and the existence of one of snan, ovfl,
| or unfl bits set in the fpsr.  If any of these are set, branch
| to the appropriate  handler for the exception in the fpsr.  Note
| that this fix is only for d43b parts, and is skipped if the
| version number is not $40.
| 
|
        .global real_inex
        .global inex
inex:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        cmpib           #VER_40,(%sp)           |test version number
        bnes            not_fmt40
        fmovel          %fpsr,-(%sp)
        btstb           #E1,E_BYTE(%a6)         |test for E1 set
        beqs            not_b1232
        btstb           #snan_bit,2(%sp) |test for snan
        beq             inex_ckofl
        addl            #4,%sp
        frestore        (%sp)+
        unlk            %a6
        bra             snan
inex_ckofl:
        btstb           #ovfl_bit,2(%sp) |test for ovfl
        beq             inex_ckufl 
        addl            #4,%sp
        frestore        (%sp)+
        unlk            %a6
        bra             ovfl
inex_ckufl:
        btstb           #unfl_bit,2(%sp) |test for unfl
        beq             not_b1232
        addl            #4,%sp
        frestore        (%sp)+
        unlk            %a6
        bra             unfl

|
| We do not have the bug 1232 case.  Clean up the stack and call
| real_inex.
|
not_b1232:
        addl            #4,%sp
        frestore        (%sp)+
        unlk            %a6

real_inex:

        addl            #1,siginex              |for standalone testing

        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
not_fmt40:
        bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
        beqs            inex_cke1
|
| Clear dirty bit on dest resister in the frame before branching
| to b1238_fix.
|
        moveml          %d0/%d1,USER_DA(%a6)
        bfextu          CMDREG1B(%a6){#6:#3},%d0                |get dest reg no
        bclrb           %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
        bsrl            b1238_fix               |test for bug1238 case
        moveml          USER_DA(%a6),%d0/%d1
        bras            inex_done
inex_cke1:
        bclrb           #E1,E_BYTE(%a6)
inex_done:
        frestore        (%sp)+
        unlk            %a6

        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)
        
|
|       Overflow exception
|
        |xref   fpsp_ovfl
        .global real_ovfl
        .global ovfl
ovfl:
        jmp     fpsp_ovfl
real_ovfl:

        addl            #1,sigovfl              |for standalone testing

        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
        bnes            ovfl_done
        bclrb           #E1,E_BYTE(%a6)
ovfl_done:
        frestore        (%sp)+
        unlk            %a6

        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)
        
|
|       Underflow exception
|
        |xref   fpsp_unfl
        .global real_unfl
        .global unfl
unfl:
        jmp     fpsp_unfl
real_unfl:

        addl            #1,sigunfl              |for standalone testing

        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
        bnes            unfl_done
        bclrb           #E1,E_BYTE(%a6)
unfl_done:
        frestore        (%sp)+
        unlk            %a6

        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)
        
|
|       Signalling NAN exception
|
        |xref   fpsp_snan
        .global real_snan
        .global snan
snan:
        jmp     fpsp_snan
real_snan:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E1,E_BYTE(%a6) |snan is always an E1 exception
        frestore        (%sp)+
        unlk            %a6

        addl            #1,sigsnan              |for standalone testing

        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)
        
|
|       Operand Error exception
|
        |xref   fpsp_operr
        .global real_operr
        .global operr
operr:
        jmp     fpsp_operr
real_operr:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E1,E_BYTE(%a6) |operr is always an E1 exception
        frestore        (%sp)+
        unlk            %a6

        addl            #1,sigoperr             |for standalone testing


        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)

        
|
|       BSUN exception
|
|       This sample handler simply clears the nan bit in the FPSR.
|
        |xref   fpsp_bsun
        .global real_bsun
        .global bsun
bsun:
        jmp     fpsp_bsun
real_bsun:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E1,E_BYTE(%a6) |bsun is always an E1 exception
        fmovel          %FPSR,-(%sp)
        bclrb           #nan_bit,(%sp)
        fmovel          (%sp)+,%FPSR
        frestore        (%sp)+
        unlk            %a6

        addl            #1,sigbsun              |for standalone testing



        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)

|
|       F-line exception
|
|       A 'real' F-line exception is one that the FPSP isn't supposed to 
|       handle. E.g. an instruction with a co-processor ID that is not 1.
|
|
        |xref   fpsp_fline
        .global real_fline
        .global fline
fline:
        jmp     fpsp_fline
real_fline:

        addl            #1,sigunimp             |for standalone testing


        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)

|
|       Unsupported data type exception
|
        |xref   fpsp_unsupp
        .global real_unsupp
        .global unsupp
unsupp:
        jmp     fpsp_unsupp
real_unsupp:
        link            %a6,#-LOCAL_SIZE
        fsave           -(%sp)
        bclrb           #E1,E_BYTE(%a6) |unsupp is always an E1 exception
        frestore        (%sp)+
        unlk            %a6

        addl            #1,sigunsupp            |for standalone testing


        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
                                        | signifies that the stack frame
                                        | is NOT for syscall
        movel   %sp,%sp@-               | stack frame pointer argument
        bsrl    SYMBOL_NAME(trap_c)
        addql   #4,%sp
        bral    SYMBOL_NAME(ret_from_exception)

|
|       Trace exception
|
        .global real_trace
real_trace:
        |
        bral    SYMBOL_NAME(trap)

|
|       fpsp_fmt_error --- exit point for frame format error
|
|       The fpu stack frame does not match the frames existing
|       or planned at the time of this writing.  The fpsp is
|       unable to handle frame sizes not in the following
|       version:size pairs:
|
|       {4060, 4160} - busy frame
|       {4028, 4130} - unimp frame
|       {4000, 4100} - idle frame
|
|       This entry point simply holds an f-line illegal value.  
|       Replace this with a call to your kernel panic code or
|       code to handle future revisions of the fpu.
|
        .global fpsp_fmt_error
fpsp_fmt_error:

        .long   0xf27f0000      |f-line illegal 

|
|       fpsp_done --- FPSP exit point
|
|       The exception has been handled by the package and we are ready
|       to return to user mode, but there may be OS specific code
|       to execute before we do.  If there is, do it now.
|
|

        .global fpsp_done
fpsp_done:
        btst    #0x5,%sp@               | supervisor bit set in saved SR?
        beq     Lnotkern
        rte
Lnotkern:
        tstl    SYMBOL_NAME(need_resched)
        bne     Lmustsched
        rte
Lmustsched:
        SAVE_ALL
        moveq   #-1,%d0
        movel   %d0,%sp@(LOFF_ORIG_D0)    | indicate stack frame not for syscall
        bral    SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc..


|
|       mem_write --- write to user or supervisor address space
|
| Writes to memory while in supervisor mode.  copyout accomplishes
| this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
| If you don't have copyout, use the local copy of the function below.
|
|       a0 - supervisor source address
|       a1 - user destination address
|       d0 - number of bytes to write (maximum count is 12)
|
| The supervisor source address is guaranteed to point into the supervisor
| stack.  The result is that a UNIX
| process is allowed to sleep as a consequence of a page fault during
| copyout.  The probability of a page fault is exceedingly small because
| the 68040 always reads the destination address and thus the page
| faults should have already been handled.
|
| If the EXC_SR shows that the exception was from supervisor space,
| then just do a dumb (and slow) memory move.  In a UNIX environment
| there shouldn't be any supervisor mode floating point exceptions.
|
        .global mem_write
mem_write:
        btstb   #5,EXC_SR(%a6)  |check for supervisor state
        beqs    user_write
super_write:
        moveb   (%a0)+,(%a1)+
        subql   #1,%d0
        bnes    super_write
        rts
user_write:
        movel   %d1,-(%sp)      |preserve d1 just in case
        movel   %d0,-(%sp)
        movel   %a1,-(%sp)
        movel   %a0,-(%sp)
        jsr             copyout
        addw    #12,%sp
        movel   (%sp)+,%d1
        rts
|
|       mem_read --- read from user or supervisor address space
|
| Reads from memory while in supervisor mode.  copyin accomplishes
| this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
| If you don't have copyin, use the local copy of the function below.
|
| The FPSP calls mem_read to read the original F-line instruction in order
| to extract the data register number when the 'Dn' addressing mode is
| used.
|
|Input:
|       a0 - user source address
|       a1 - supervisor destination address
|       d0 - number of bytes to read (maximum count is 12)
|
| Like mem_write, mem_read always reads with a supervisor 
| destination address on the supervisor stack.  Also like mem_write,
| the EXC_SR is checked and a simple memory copy is done if reading
| from supervisor space is indicated.
|
        .global mem_read
mem_read:
        btstb   #5,EXC_SR(%a6)  |check for supervisor state
        beqs    user_read
super_read:
        moveb   (%a0)+,(%a1)+
        subql   #1,%d0
        bnes    super_read
        rts
user_read:
        movel   %d1,-(%sp)      |preserve d1 just in case
        movel   %d0,-(%sp)
        movel   %a1,-(%sp)
        movel   %a0,-(%sp)
        jsr             copyin
        addw    #12,%sp
        movel   (%sp)+,%d1
        rts

|
| Use these routines if your kernel doesn't have copyout/copyin equivalents.
| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
| and copyin overwrites SFC.
|
copyout:
        movel   4(%sp),%a0      | source
        movel   8(%sp),%a1      | destination
        movel   12(%sp),%d0     | count
        subl    #1,%d0          | dec count by 1 for dbra
        movel   #1,%d1
        movec   %d1,%DFC                | set dfc for user data space
moreout:
        moveb   (%a0)+,%d1      | fetch supervisor byte
        movesb  %d1,(%a1)+      | write user byte
        dbf     %d0,moreout
        rts

copyin:
        movel   4(%sp),%a0      | source
        movel   8(%sp),%a1      | destination
        movel   12(%sp),%d0     | count
        subl    #1,%d0          | dec count by 1 for dbra
        movel   #1,%d1
        movec   %d1,%SFC                | set sfc for user space
morein:
        movesb  (%a0)+,%d1      | fetch user byte
        moveb   %d1,(%a1)+      | write supervisor byte
        dbf     %d0,morein
        rts

        |end

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.