NetBSD/sys/arch/m68k/fpsp/netbsd.sa

448 lines
11 KiB
Plaintext

* $NetBSD: netbsd.sa,v 1.5 2001/10/02 06:34:52 chs Exp $
* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
* M68000 Hi-Performance Microprocessor Division
* M68040 Software Package
*
* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
* All rights reserved.
*
* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
* To the maximum extent permitted by applicable law,
* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
* PARTICULAR PURPOSE and any warranty against infringement with
* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
* and any accompanying written materials.
*
* To the maximum extent permitted by applicable law,
* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
* SOFTWARE. Motorola assumes no responsibility for the maintenance
* and support of the SOFTWARE.
*
* You are hereby granted a copyright license to use, modify, and
* distribute the SOFTWARE so long as this entire notice is retained
* without alteration in any modified and/or redistributed versions,
* and that such modified versions are clearly identified as such.
* No licenses are granted by implication, estoppel or otherwise
* under any patents or trademarks of Motorola, Inc.
*
* 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.
*
SKELETON IDNT 2,1 Motorola 040 Floating Point Software Package
section 15
*
* The following counters are used for standalone testing
*
section 8
include fpsp.h
*
* XXX Note, this is NOT valid Motorola syntax, but what else can we do?
*
#include <machine/asm.h>
xref b1238_fix
xref _C_LABEL(mmutype)
*
* Divide by Zero exception
*
* All dz exceptions are 'real', hence no fpsp_dz entry point.
*
xdef dz
xdef real_dz
dz:
cmp.l #-2,_C_LABEL(mmutype)
bne.l _C_LABEL(fpfault)
real_dz:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E1,E_BYTE(a6)
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* 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.
*
*
xdef real_inex
xdef inex
inex:
cmp.l #-2,_C_LABEL(mmutype)
bne.l _C_LABEL(fpfault)
link a6,#-LOCAL_SIZE
fsave -(sp)
cmpi.b #VER_40,(sp) ;test version number
bne.b not_fmt40
fmove.l fpsr,-(sp)
btst.b #E1,E_BYTE(a6) ;test for E1 set
beq.b not_b1232
btst.b #snan_bit,2(sp) ;test for snan
beq inex_ckofl
addq.l #4,sp
frestore (sp)+
unlk a6
bra snan
inex_ckofl:
btst.b #ovfl_bit,2(sp) ;test for ovfl
beq inex_ckufl
addq.l #4,sp
frestore (sp)+
unlk a6
bra ovfl
inex_ckufl:
btst.b #unfl_bit,2(sp) ;test for unfl
beq not_b1232
addq.l #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:
addq.l #4,sp
frestore (sp)+
unlk a6
real_inex:
link a6,#-LOCAL_SIZE
fsave -(sp)
not_fmt40:
bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
beq.b inex_cke1
*
* Clear dirty bit on dest resister in the frame before branching
* to b1238_fix.
*
movem.l d0/d1,USER_DA(a6)
bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no
bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit
bsr.l b1238_fix ;test for bug1238 case
movem.l USER_DA(a6),d0/d1
bra.b inex_done
inex_cke1:
bclr.b #E1,E_BYTE(a6)
inex_done:
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* Overflow exception
*
xref fpsp_ovfl
xdef real_ovfl
xdef ovfl
ovfl:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_ovfl
jmp _C_LABEL(fpfault)
real_ovfl:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
bne.b ovfl_done
bclr.b #E1,E_BYTE(a6)
ovfl_done:
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* Underflow exception
*
xref fpsp_unfl
xdef real_unfl
xdef unfl
unfl:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_unfl
jmp _C_LABEL(fpfault)
real_unfl:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag
bne.b unfl_done
bclr.b #E1,E_BYTE(a6)
unfl_done:
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* Signalling NAN exception
*
xref fpsp_snan
xdef real_snan
xdef snan
snan:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_snan
jmp _C_LABEL(fpfault)
real_snan:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* Operand Error exception
*
xref fpsp_operr
xdef real_operr
xdef operr
operr:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_operr
jmp _C_LABEL(fpfault)
real_operr:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* BSUN exception
*
* This sample handler simply clears the nan bit in the FPSR.
*
xref fpsp_bsun
xdef real_bsun
xdef bsun
bsun:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_bsun
jmp _C_LABEL(fpfault)
real_bsun:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception
fmove.l FPSR,-(sp)
bclr.b #nan_bit,(sp)
fmove.l (sp)+,FPSR
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* 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
xdef real_fline
xdef fline
fline:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_fline
jmp _C_LABEL(fpfault)
real_fline:
jmp _C_LABEL(fpfault)
*
* Unsupported data type exception
*
xref fpsp_unsupp
xdef real_unsupp
xdef unsupp
unsupp:
cmp.l #-2,_C_LABEL(mmutype)
beq.l fpsp_unsupp
jmp _C_LABEL(fpfault)
real_unsupp:
link a6,#-LOCAL_SIZE
fsave -(sp)
bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception
frestore (sp)+
unlk a6
jmp _C_LABEL(fpfault)
*
* Trace exception
*
xdef real_trace
real_trace:
rte
*
* 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.
*
xdef fpsp_fmt_error
fpsp_fmt_error:
pea 1f
jsr _C_LABEL(panic)
dc.l $f27f0000 ;f-line illegal
1:
.asciz "bad floating point stack frame"
.even
*
* 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.
*
*
xref _ASM_LABEL(rei)
xdef fpsp_done
fpsp_done:
jmp _ASM_LABEL(rei)
*
* 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.
*
xdef mem_write
mem_write:
btst.b #5,EXC_SR(a6) ;check for supervisor state
beq.b user_write
super_write:
move.b (a0)+,(a1)+
subq.l #1,d0
bne.b super_write
rts
user_write:
move.l d1,-(sp) ;preserve d1 just in case
move.l d0,-(sp)
move.l a1,-(sp)
move.l a0,-(sp)
jsr _C_LABEL(copyout)
add.l #12,sp
move.l (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.
*
xdef mem_read
mem_read:
btst.b #5,EXC_SR(a6) ;check for supervisor state
beq.b user_read
super_read:
move.b (a0)+,(a1)+
subq.l #1,d0
bne.b super_read
rts
user_read:
move.l d1,-(sp) ;preserve d1 just in case
move.l d0,-(sp)
move.l a1,-(sp)
move.l a0,-(sp)
jsr _C_LABEL(copyin)
add.l #12,sp
move.l (sp)+,d1
rts
end