head     56.3;
access   ;
symbols  ;
locks    ; strict;
comment  @# @;


56.3
date     93.01.27.13.57.19;  author jwh;  state Exp;
branches ;
next     56.2;

56.2
date     93.01.27.12.28.51;  author jwh;  state Exp;
branches ;
next     56.1;

56.1
date     91.11.07.12.30.22;  author jwh;  state Exp;
branches ;
next     1.1;

1.1
date     91.03.13.08.53.49;  author jwh;  state Exp;
branches ;
next     ;


desc
@@


56.3
log
@
pws2rcs automatic delta on Wed Jan 27 13:14:25 MST 1993
@
text
@*============================================================================
* This file, together with the file MAIN.TEXT, provides the intialization
* code and code to hook the the floating point package into the PaWS
* system. The file MAIN.TEXT is the main program for the module FP40,
* including the code to p-load this module. The "real_xxxx" routines
* in this module are set up by MAIN, and also MAIN hooks the FP Package
* entry points into high memory.
*============================================================================
*
*
*       skeleton.sa 3.1 12/10/90
*
*       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.


*
*       The following counters are used for standalone testing
*
		lmode   sigunimp
		lmode   sigbsun
		lmode   siginex
		lmode   sigdz
		lmode   sigunfl
		lmode   sigovfl
		lmode   sigoperr
		lmode   sigsnan
		lmode   sigunsupp

sigunimp        dc.l    0
sigbsun         dc.l    0
siginex         dc.l    0
sigdz           dc.l    0
sigunfl         dc.l    0
sigovfl         dc.l    0
sigoperr        dc.l    0
sigsnan         dc.l    0
sigunsupp       dc.l    0

	include fpsp_h
	lmode  dz,bsun,unfl,ovfl,operr,snan,inex
	def     which_one
	refr    b1238_fix
*
*       Divide by Zero exception
*
*       All dz exceptions are 'real', hence no fpsp_dz entry point.
*
*    def     dz
	def     real_dz
dz    equ    *
real_dz    equ    *

*       to be jammed with jmp <ea> by MAIN :
	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)
	frestore        (sp)+
	unlk            a6

	addi.l  #1,sigdz                ;for standalone testing

	rte
*
*       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 occured, 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 FPSTATUS.  If any of these are set, branch
* to the appropriate  handler for the exception in the FPSTATUS.  Note
* that this fix is only for d43b parts, and is skipped if the
* version number is not $40.
*
*
	def     real_inex
	def     inex
inex    equ    *
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	cmpi.b          #VER_40,(sp)            ;test version number
	bne.b           real_inex
	fmove.l         FPSTATUS,-(sp)
	btst            #E1,E_BYTE(a6)          ;test for E1 set
	beq.b           not_b1232
	btst            #snan_bit,2(sp) ;test for snan
	beq             inex_ckofl
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6
	bra             snan
inex_ckofl    equ    *
	btst            #ovfl_bit,2(sp) ;test for ovfl
	beq             inex_ckufl
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6
	bra             ovfl
inex_ckufl    equ    *
	btst            #unfl_bit,2(sp) ;test for unfl
	beq             not_b1232
	add.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    equ    *
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6

real_inex    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,siginex              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #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            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    equ    *
	bclr            #E1,E_BYTE(a6)
inex_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Overflow exception
*
	refr    fpsp_ovfl
	def     real_ovfl
	def     ovfl
ovfl    equ    *
	jmp     fpsp_ovfl
real_ovfl    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigovfl              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E3,E_BYTE(a6)          ;clear and test E3 flag
	bne.b           ovfl_done
	bclr            #E1,E_BYTE(a6)
ovfl_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Underflow exception
*
	refr    fpsp_unfl
	def     real_unfl
	def     unfl
unfl    equ    *
	jmp     fpsp_unfl
real_unfl    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigunfl              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E3,E_BYTE(a6)          ;clear and test E3 flag
	bne.b           unfl_done
	bclr            #E1,E_BYTE(a6)
unfl_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Signalling NAN exception
*
	refr    fpsp_snan
	def     real_snan
	def     snan
snan    equ    *
	jmp     fpsp_snan
real_snan    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;snan is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigsnan              ;for standalone testing
	rte

*
*       Operand Error exception
*
	refr    fpsp_operr
	def     real_operr
	def     operr
operr    equ    *
	jmp     fpsp_operr
real_operr    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;operr is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigoperr             ;for standalone testing

	rte

*
*       BSUN exception
*
*       This sample handler simply clears the nan bit in the FPSTATUS.
*
	refr    fpsp_bsun
	def     real_bsun
	def     bsun
bsun    equ    *
	jmp     fpsp_bsun
real_bsun    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;bsun is always an E1 exception
	fmove.l         FPSTATUS,-(sp)
	bclr            #nan_bit,(sp)
	fmove.l         (sp)+,FPSTATUS
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigbsun              ;for standalone testing

	rte

*
*       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.
*
*
	refr    fpsp_fline
	def     real_fline
	def     fline
fline    equ    *
	jmp     fpsp_fline
real_fline    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigunimp             ;for standalone testing

	rte

*
*       Unsupported data type exception
*
	refr    fpsp_unsupp
	def     real_unsupp
	def     unsupp
unsupp    equ    *
	jmp     fpsp_unsupp
real_unsupp    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;unsupp is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigunsupp            ;for standalone testing

	rte

*
*       Trace exception
*
	def     real_trace
real_trace    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	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.
*
	def     fpsp_fmt_error
fpsp_fmt_error    equ    *

	dc.l    $f27f0000       ;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.
*
*
	def     fpsp_done
fpsp_done    equ    *
	rte

*
*       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.
*
	def     mem_write
mem_write    equ    *
	btst    #5,EXC_SR(a6)   ;check for supervisor state
	beq.b   user_write
super_write    equ    *
	move.b  (a0)+,(a1)+
	subq.l  #1,d0
	bne.b   super_write
	rts
user_write    equ    *
	move.l  d1,-(sp)        ;preserve d1 just in case
	move.l  d0,-(sp)
	move.l  a1,-(sp)
	move.l  a0,-(sp)
	jsr             copyout
	add.w   #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.
*
	def     mem_read
mem_read    equ    *
	btst    #5,EXC_SR(a6)   ;check for supervisor state
	beq.b   user_read
super_read    equ    *
	move.b  (a0)+,(a1)+
	subq.l  #1,d0
	bne.b   super_read
	rts
user_read    equ    *
	move.l  d1,-(sp)        ;preserve d1 just in case
	move.l  d0,-(sp)
	move.l  a1,-(sp)
	move.l  a0,-(sp)
	jsr             copyin
	add.w   #12,sp
	move.l  (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    equ    *
	move.l  4(sp),a0        ; source
	move.l  8(sp),a1        ; destination
	move.l  12(sp),d0       ; count
	sub.l   #1,d0           ; dec count by 1 for dbra
	move.l  #1,d1
	movec   d1,DFC          ; set dfc for user data space
moreout    equ    *
	move.b  (a0)+,d1        ; fetch supervisor byte
	moves.b d1,(a1)+        ; write user byte
	dbf     d0,moreout
	rts

copyin    equ    *
	move.l  4(sp),a0        ; source
	move.l  8(sp),a1        ; destination
	move.l  12(sp),d0       ; count
	sub.l   #1,d0           ; dec count by 1 for dbra
	move.l  #1,d1
	movec   d1,SFC          ; set sfc for user space
morein    equ    *
	moves.b (a0)+,d1        ; fetch user byte
	move.b  d1,(a1)+        ; write supervisor byte
	dbf     d0,morein
	rts

* I had to add the following code for PaWS because the vector table is loaded
* with the same thing for exceptions #48-#54 (FFFFFEE0). The PaWS exception
* handler then looks at the FPSTATUS register to figure out exactly which one
* it is. I looked at the code for the PaWS exception handler and also table
* 2-7 of the 68040 manual to produce the following code. We test for high
* to low priority exceptions, in that order. If a bit is set in the FPSTATUS
* register, we make sure that exception class is enabled before branching
* the the handler.
*
which_one     equ        *
	      move.l     d0,-(sp)    ; save d0
	      move.l     d1,-(SP)    ; save d1
	      move.l     d2,-(SP)    ; save d2
	      fsave      -(sp)       ; save the FP Context
	      fmove.l    FPSTATUS,d0
	      fmove.l    FPCONTROL,d1
	      fmove.l    FPIADDR,d2
	      btst       #15,d0
	      beq.s      carry_on
	      btst       #15,d1      ; enabled ??
	      beq.s      carry_on
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        bsun        ; it was bsun exception
carry_on      equ        *
	      btst       #14,d0
	      beq.s      carry_on1
	      btst       #14,d1      ; enabled ??
	      beq.s      carry_on1
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        snan        ; it was snan exception
carry_on1     equ        *
	      btst       #13,d0
	      beq.s      carry_on2
	      btst       #13,d1      ; enabled ??
	      beq.s      carry_on2
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        operr       ; it was divide by zero
carry_on2     equ        *
	      btst       #12,d0
	      beq.s      carry_on3
	      btst       #12,d1      ; enabled ??
	      beq.s      carry_on3
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d1
	      jmp        ovfl       ; it was operand error
carry_on3     equ        *
	      btst       #11,d0
	      beq.s      carry_on4
	      btst       #11,d1      ; enabled ??
	      beq.s      carry_on4
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d1
	      jmp        unfl
carry_on4     equ        *
	      btst       #10,d0
	      beq.s      carry_on5
	      btst       #10,d1      ; enabled ??
	      beq.s      carry_on5
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d1
	      move.l     (sp)+,d0    ; restore d0
	      jmp        dz
carry_on5     equ        *
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d1
	      move.l     (sp)+,d0    ;         d0
	      jmp        inex        ; only thing left
	      rte                    ; should never get here
	end
@


56.2
log
@
pws2rcs automatic delta on Wed Jan 27 11:57:27 MST 1993
@
text
@d1 606
@


56.1
log
@Automatic bump of revision number for PWS version 3.25
@
text
@a0 606
*============================================================================
* This file, together with the file MAIN.TEXT, provides the intialization
* code and code to hook the the floating point package into the PaWS
* system. The file MAIN.TEXT is the main program for the module FP40,
* including the code to p-load this module. The "real_xxxx" routines
* in this module are set up by MAIN, and also MAIN hooks the FP Package
* entry points into high memory.
*============================================================================
*
*
*       skeleton.sa 3.1 12/10/90
*
*       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.


*
*       The following counters are used for standalone testing
*
		lmode   sigunimp
		lmode   sigbsun
		lmode   siginex
		lmode   sigdz
		lmode   sigunfl
		lmode   sigovfl
		lmode   sigoperr
		lmode   sigsnan
		lmode   sigunsupp

sigunimp        dc.l    0
sigbsun         dc.l    0
siginex         dc.l    0
sigdz           dc.l    0
sigunfl         dc.l    0
sigovfl         dc.l    0
sigoperr        dc.l    0
sigsnan         dc.l    0
sigunsupp       dc.l    0

	include fpsp_h
	lmode  dz,bsun,unfl,ovfl,operr,snan,inex
	def     which_one
	refr    b1238_fix
*
*       Divide by Zero exception
*
*       All dz exceptions are 'real', hence no fpsp_dz entry point.
*
*    def     dz
	def     real_dz
dz    equ    *
real_dz    equ    *

*       to be jammed with jmp <ea> by MAIN :
	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)
	frestore        (sp)+
	unlk            a6

	addi.l  #1,sigdz                ;for standalone testing

	rte
*
*       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 occured, 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 FPSTATUS.  If any of these are set, branch
* to the appropriate  handler for the exception in the FPSTATUS.  Note
* that this fix is only for d43b parts, and is skipped if the
* version number is not $40.
*
*
	def     real_inex
	def     inex
inex    equ    *
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	cmpi.b          #VER_40,(sp)            ;test version number
	bne.b           real_inex
	fmove.l         FPSTATUS,-(sp)
	btst            #E1,E_BYTE(a6)          ;test for E1 set
	beq.b           not_b1232
	btst            #snan_bit,2(sp) ;test for snan
	beq             inex_ckofl
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6
	bra             snan
inex_ckofl    equ    *
	btst            #ovfl_bit,2(sp) ;test for ovfl
	beq             inex_ckufl
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6
	bra             ovfl
inex_ckufl    equ    *
	btst            #unfl_bit,2(sp) ;test for unfl
	beq             not_b1232
	add.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    equ    *
	add.l           #4,sp
	frestore        (sp)+
	unlk            a6

real_inex    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,siginex              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #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            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    equ    *
	bclr            #E1,E_BYTE(a6)
inex_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Overflow exception
*
	refr    fpsp_ovfl
	def     real_ovfl
	def     ovfl
ovfl    equ    *
	jmp     fpsp_ovfl
real_ovfl    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigovfl              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E3,E_BYTE(a6)          ;clear and test E3 flag
	bne.b           ovfl_done
	bclr            #E1,E_BYTE(a6)
ovfl_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Underflow exception
*
	refr    fpsp_unfl
	def     real_unfl
	def     unfl
unfl    equ    *
	jmp     fpsp_unfl
real_unfl    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigunfl              ;for standalone testing

	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E3,E_BYTE(a6)          ;clear and test E3 flag
	bne.b           unfl_done
	bclr            #E1,E_BYTE(a6)
unfl_done    equ    *
	frestore        (sp)+
	unlk            a6
	rte

*
*       Signalling NAN exception
*
	refr    fpsp_snan
	def     real_snan
	def     snan
snan    equ    *
	jmp     fpsp_snan
real_snan    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;snan is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigsnan              ;for standalone testing
	rte

*
*       Operand Error exception
*
	refr    fpsp_operr
	def     real_operr
	def     operr
operr    equ    *
	jmp     fpsp_operr
real_operr    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;operr is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigoperr             ;for standalone testing

	rte

*
*       BSUN exception
*
*       This sample handler simply clears the nan bit in the FPSTATUS.
*
	refr    fpsp_bsun
	def     real_bsun
	def     bsun
bsun    equ    *
	jmp     fpsp_bsun
real_bsun    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;bsun is always an E1 exception
	fmove.l         FPSTATUS,-(sp)
	bclr            #nan_bit,(sp)
	fmove.l         (sp)+,FPSTATUS
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigbsun              ;for standalone testing

	rte

*
*       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.
*
*
	refr    fpsp_fline
	def     real_fline
	def     fline
fline    equ    *
	jmp     fpsp_fline
real_fline    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000

	addi.l          #1,sigunimp             ;for standalone testing

	rte

*
*       Unsupported data type exception
*
	refr    fpsp_unsupp
	def     real_unsupp
	def     unsupp
unsupp    equ    *
	jmp     fpsp_unsupp
real_unsupp    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	link            a6,#-LOCAL_SIZE
	fsave           -(sp)
	bclr            #E1,E_BYTE(a6)  ;unsupp is always an E1 exception
	frestore        (sp)+
	unlk            a6

	addi.l          #1,sigunsupp            ;for standalone testing

	rte

*
*       Trace exception
*
	def     real_trace
real_trace    equ    *
*       to be jammed with jmp <ea> by MAIN :

	DC.W            $0000,$0000,$0000
	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.
*
	def     fpsp_fmt_error
fpsp_fmt_error    equ    *

	dc.l    $f27f0000       ;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.
*
*
	def     fpsp_done
fpsp_done    equ    *
	rte

*
*       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.
*
	def     mem_write
mem_write    equ    *
	btst    #5,EXC_SR(a6)   ;check for supervisor state
	beq.b   user_write
super_write    equ    *
	move.b  (a0)+,(a1)+
	subq.l  #1,d0
	bne.b   super_write
	rts
user_write    equ    *
	move.l  d1,-(sp)        ;preserve d1 just in case
	move.l  d0,-(sp)
	move.l  a1,-(sp)
	move.l  a0,-(sp)
	jsr             copyout
	add.w   #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.
*
	def     mem_read
mem_read    equ    *
	btst    #5,EXC_SR(a6)   ;check for supervisor state
	beq.b   user_read
super_read    equ    *
	move.b  (a0)+,(a1)+
	subq.l  #1,d0
	bne.b   super_read
	rts
user_read    equ    *
	move.l  d1,-(sp)        ;preserve d1 just in case
	move.l  d0,-(sp)
	move.l  a1,-(sp)
	move.l  a0,-(sp)
	jsr             copyin
	add.w   #12,sp
	move.l  (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    equ    *
	move.l  4(sp),a0        ; source
	move.l  8(sp),a1        ; destination
	move.l  12(sp),d0       ; count
	sub.l   #1,d0           ; dec count by 1 for dbra
	move.l  #1,d1
	movec   d1,DFC          ; set dfc for user data space
moreout    equ    *
	move.b  (a0)+,d1        ; fetch supervisor byte
	moves.b d1,(a1)+        ; write user byte
	dbf     d0,moreout
	rts

copyin    equ    *
	move.l  4(sp),a0        ; source
	move.l  8(sp),a1        ; destination
	move.l  12(sp),d0       ; count
	sub.l   #1,d0           ; dec count by 1 for dbra
	move.l  #1,d1
	movec   d1,SFC          ; set sfc for user space
morein    equ    *
	moves.b (a0)+,d1        ; fetch user byte
	move.b  d1,(a1)+        ; write supervisor byte
	dbf     d0,morein
	rts

* I had to add the following code for PaWS because the vector table is loaded
* with the same thing for exceptions #48-#54 (FFFFFEE0). The PaWS exception
* handler then looks at the FPSTATUS register to figure out exactly which one
* it is. I looked at the code for the PaWS exception handler and also table
* 2-7 of the 68040 manual to produce the following code. We test for high
* to low priority exceptions, in that order. If a bit is set in the FPSTATUS
* register, we make sure that exception class is enabled before branching
* the the handler.
*
which_one     equ        *
	      move.l     d0,-(sp)    ; save d0
	      move.l     d1,-(SP)    ; save d1
	      move.l     d2,-(SP)    ; save d2
	      fsave      -(sp)       ; save the FP Context
	      fmove.l    FPSTATUS,d0
	      fmove.l    FPCONTROL,d1
	      fmove.l    FPIADDR,d2
	      btst       #15,d0
	      beq.s      carry_on
	      btst       #15,d1      ; enabled ??
	      beq.s      carry_on
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        bsun        ; it was bsun exception
carry_on      equ        *
	      btst       #14,d0
	      beq.s      carry_on1
	      btst       #14,d1      ; enabled ??
	      beq.s      carry_on1
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        snan        ; it was snan exception
carry_on1     equ        *
	      btst       #13,d0
	      beq.s      carry_on2
	      btst       #13,d1      ; enabled ??
	      beq.s      carry_on2
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d0
	      jmp        operr       ; it was divide by zero
carry_on2     equ        *
	      btst       #12,d0
	      beq.s      carry_on3
	      btst       #12,d1      ; enabled ??
	      beq.s      carry_on3
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d1
	      jmp        ovfl       ; it was operand error
carry_on3     equ        *
	      btst       #11,d0
	      beq.s      carry_on4
	      btst       #11,d1      ; enabled ??
	      beq.s      carry_on4
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d0
	      move.l     (sp)+,d0    ; restore d1
	      jmp        unfl
carry_on4     equ        *
	      btst       #10,d0
	      beq.s      carry_on5
	      btst       #10,d1      ; enabled ??
	      beq.s      carry_on5
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d1
	      move.l     (sp)+,d0    ; restore d0
	      jmp        dz
carry_on5     equ        *
	      fmove.l    d0,FPSTATUS ; put it all back
	      fmove.l    d1,FPCONTROL ;
	      fmove.l    d2,FPIADDR
	      frestore   (sp)+
	      move.l     (sp)+,d2
	      move.l     (sp)+,d1    ; restore d1
	      move.l     (sp)+,d0    ;         d0
	      jmp        inex        ; only thing left
	      rte                    ; should never get here
	end
@


1.1
log
@Initial revision
@
text
@@
