sys7.1-doc-wip/Toolbox/InSANE/FPPrivTrap.a
2019-07-27 22:37:48 +08:00

304 lines
11 KiB
Plaintext

;
; File: FPPrivTrap.a
;
; Contains: Floating point privileged functions
;
; Written by: Apple Numerics Group, DSG
;
; Copyright: © 1985-1992 by Apple Computer, Inc., all rights reserved.
;
; This file is used in these builds:
; Change History (most recent first):
;
; <2> 1/24/92 KC Add conditional to _SysBreak Macro.
; Terror Change History:
;
; <2> 3/18/91 BG Modified the check for whether or not PrivTrap gets installed to
; be more general regarding which CPUs have FPUs.
; <1> 1/21/91 BG first checked in
LOAD 'StandardEqu.d' ; needed for HWCfgFlags check
INCLUDE 'HardwarePrivateEqu.a' ; needed for 'UniversalEqu.a'
; This is not a standard definition in the System Equates, so it is included here
If &TYPE('_SysBreak') = 'UNDEFINED' Then
MACRO
_SysBreak
MOVE.W #-490, D0
_SysError
ENDM
ENDIF
MACHINE MC68040
*
* THE FOLLOWING CODE IS DIRECTLY LIFTED FROM MPW3.2'S CSANELIBRT881.A SOURCE CODE,
* WRITTEN BY PAUL FINLAYSON, BRIAN MCGHIE, JON OKADA AND STUART MCDONALD.
*
* IF THIS CODE IS ROMMED, tFPPriv TRAP ($A097) SHOULD BE ROMMED, TOO! THEN WE
* WON'T BE CONTINUALLY INSTALLING IT ON THE FLY. A/UX & VM PEOPLE, ARE YOU LISTENING???
* THIS ISOLATION OF PRIVILEGED INSTRUCTIONS TO A SINGLE TRAP WAS FOR YOUR BENEFIT.
* WHY, AS OF THE MAC IICI, HAS NO ONE BURNT tFPPriv TRAP INTO ROM? INSTALLING IT
* ON THE FLY IS SURELY A NO-NO IN THE A/UX WORLD AND I BET THE A/UX FOLKS AREN'T
* OVERRIDDING IT... HOW COULD THEY IF INSTALLING IT IS A NO-NO?
; ***************************************
; * "Ask and ye shall receive ... " *
; ***************************************
tFPPriv EQU $A097 ; privileged instruction trap number
; _________________________________________________________________________________________
;
; InstallPrivTrap - Set up the _FPPriv trap for use, if required
;
; Expects: -None-
; Trashes: A0, D0
;
; _________________________________________________________________________________________
InstallPrivTrap PROC EXPORT
btst.b #hwCbFPU-8,HWCfgFlags; FPU installed on board? <T2>
beq.s @exit ; exit if we don't have a HW FPU <T2>
lea PrivTrap881,A0 ; A0 = PrivTrap881()
cmp.b #cpu68040,CPUFlag ; are we running on an 040 or 050?
blt.s @goForIt ; IF CPU >= 040 THEN
lea PrivTrap040,A0 ; A0 = PrivTrap040()
@goForIt ; ENDIF
MOVE.W #tFPPriv,D0 ; D0 = $A097
_SetTrapAddress ,NEWOS ; Install A-Trap
@exit rts ; return to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; privileged instruction trap
;; This routine calls trap code containing privileged instructions. If the trap
;; has not been installed it installs it. The purpose of this routine is to provide
;; compatability with future architectures which will not allow user-mode library
;; code to execute privileged instructions. TO BE ADDED: FSAVE/FRESTORE ENTRIES?
;;
;; Trap conventions:
;; Registers D1,D2,A0,A1,A2 are restored to their pre-call values after the
;; trap call. Registers D0,A0,A1 are visible to the trap code and provide the
;; mechanism for input values to the trap code. D0 is the only register that
;; can be changed by the trap code (after return to the caller). TST.W D0 is
;; the last instruction before return to the program calling the trap.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 888888888888 888888888888 1111
; 88 88 88 88 11 11
; 88 88 88 88 11 11
; 88 88 88 88 11
; 888888888888 888888888888 11
; 88 88 88 88 11
; 88 88 88 88 11
; 88 88 88 88 11
; 888888888888 888888888888 1111111111
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ALIGN 16 ; align on nearest cache line boundary
EXPORT PrivTrap881 ; needed for SANE / Startup code
PrivTrap881
CMP.W #0,D0
BEQ.S SetExcept881 ; Set the exceptions contained in A0
CMP.W #1,D0
BEQ.S GetTrapVec881 ; GetTrapVector code
CMP.W #2,D0
BEQ.S SetTrapVec881 ; SetTrapVector code
_SysBreak ; Error in selector code
rts ; .. exit <T2>
; SkipMarkRel dc.w SkipMark-QADDX ; offset to SkipMark from QADDX <9/30/90-S.McD.>
SetExcept881
FNOP ; Ensure 881 is idle
MOVE.L A0,D1 ; Copy exceptions into D1
FSAVE -(SP) ; Save 881 environment
FMOVE.L FPSR,D0 ; D0 <- FPSR
AND.W #$00FF,D0 ; Clear previous op flags <5/12/90-S.McD.>
OR.W D1,D0 ; Set proper exceptions
FMOVE.L D0,FPSR ; Move results back to FPSR
FMOVE.L FPCR,D0 ; D0 <- FPCR
AND.W D1,D0 ; Find exception intersection
ANDI.L #$FF00,D0 ; Mask off low byte and high word
BEQ.S SkipMark ; If no intersection, then don't
; mark exception pending bit
LEA SkipMark,A0 ; A0 := @FRESTORE <8/31/90-S.McD.>
FMOVEM.L A0,FPIAR ; FPIAR := A0 <8/31/90-S.McD.>
;*
;* Alas, once tFPPriv trap has installed itself, SkipMark is no longer in PACK4!
;* Since we want FPIAR to always point to something inside PACK4, we must be more
;* careful how we set it up. Here's how using QADDX's JMP island at $0B6C:
;*
; --- Actually, with this code installed in ROM, you DO know where SkipMark
; --- is, so you can use the address as before. B. Galcher (1/16/91)
;
; MOVEA.L $0B6E,A0 ; A0 := &QADDX <9/30/90-S.McD.>
; ADDA.W SkipMarkRel,A0 ; A0 := &SkipMark in PACK4 <9/30/90-S.McD.>
CLR.L D0
MOVE.B 1(SP),D0 ; Load state frame size
BCLR #3,(SP,D0) ; Clear bit 27 of BIU
SkipMark
FRESTORE (SP)+ ; Restore 881 environment
RTS
GetTrapVec881
MOVE.L #$0C0,A1 ; A1 <- &Unordered vector in table
MOVE.L (A1)+,(A0)+ ; Traps.Unordered <- &Unordered vector
MOVE.L (A1)+,(A0)+ ; Traps.Inexact <- &Inexact vector
MOVE.L (A1)+,(A0)+ ; Traps.DivByZero <- &DivByZero vector
MOVE.L (A1)+,(A0)+ ; Traps.Underflow <- &Underflow vector
MOVE.L (A1)+,(A0)+ ; Traps.OpError <- &OpError vector
MOVE.L (A1)+,(A0)+ ; Traps.Overflow <- &Overflow vector
MOVE.L (A1)+,(A0)+ ; Traps.SigNaN <- &SigNaN vector
RTS
SetTrapVec881
MOVE.L #$0C0,A1 ; A1 <- &Unordered vector in table
MOVE.L (A0)+,(A1)+ ; &Unordered vector <- Traps.Unordered
MOVE.L (A0)+,(A1)+ ; &Inexact vector <- Traps.Inexact
MOVE.L (A0)+,(A1)+ ; &DivByZero vector <- Traps.DivByZero
MOVE.L (A0)+,(A1)+ ; &Underflow vector <- Traps.Underflow
MOVE.L (A0)+,(A1)+ ; &OpError vector <- Traps.OpError
MOVE.L (A0)+,(A1)+ ; &Overflow vector <- Traps.Overflow
MOVE.L (A0)+,(A1)+ ; &SigNaN vector <- Traps.SigNaN
RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 000000000000 444444 000000000000
; 00 00 44 44 00 00
; 00 00 44 44 00 00
; 00 00 44 44 00 00
; 00 00 44 44 00 00
; 00 00 444444444444444 00 00
; 00 00 44 00 00
; 00 00 44 00 00
; 000000000000 44 000000000000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FPBSUN_VEC040 EQU $1FCC ; special FP exception vector addresses <12/03/90, JPO>
FPUNFL_VEC040 EQU $1FD0
FPOPERR_VEC040 EQU $1FD4
FPOVFL_VEC040 EQU $1FD8
FPSNAN_VEC040 EQU $1FDC
ALIGN 16 ; align on nearest cache line boundary
EXPORT PrivTrap040 ; needed by SANE / Startup code
PrivTrap040
CMP.W #0,D0
BEQ.S SetExcept040 ; Set the exceptions contained in A0
CMP.W #1,D0
BEQ.S GetTrapVec040 ; GetTrapVector code
CMP.W #2,D0
BEQ.S SetTrapVec040 ; SetTrapVector code
_SysBreak ; Error in selector code
rts ; .. exit <T2>
GetTrapVec040 ; 040-style
MOVE.L #$0C4,A1 ; A1 <- &Inexact vector in table
MOVE.L (FPBSUN_VEC040).W,(A0)+ ; Traps.Unordered <- &Unordered vector
MOVE.L (A1)+,(A0)+ ; Traps.Inexact <- &Inexact vector
MOVE.L (A1),(A0)+ ; Traps.DivByZero <- &DivByZero vector
MOVE.L (FPUNFL_VEC040).W,(A0)+ ; Traps.Underflow <- &Underflow vector
MOVE.L (FPOPERR_VEC040).W,(A0)+; Traps.OpError <- &OpError vector
MOVE.L (FPOVFL_VEC040).W,(A0)+ ; Traps.Overflow <- &Overflow vector
MOVE.L (FPSNAN_VEC040).W,(A0)+ ; Traps.SigNaN <- &SigNaN vector
RTS
SetTrapVec040
MOVE.L #$0C4,A1 ; A1 <- &Inexact vector in table
MOVE.L (A0)+,(FPBSUN_VEC040).W ; &Unordered vector <- Traps.Unordered
MOVE.L (A0)+,(A1)+ ; &Inexact vector <- Traps.Inexact
MOVE.L (A0)+,(A1) ; &DivByZero vector <- Traps.DivByZero
MOVE.L (A0)+,(FPUNFL_VEC040).W ; &Underflow vector <- Traps.Underflow
MOVE.L (A0)+,(FPOPERR_VEC040).W; &OpError vector <- Traps.OpError
MOVE.L (A0)+,(FPOVFL_VEC040).W ; &Overflow vector <- Traps.Overflow
MOVE.L (A0)+,(FPSNAN_VEC040).W ; &SigNaN vector <- Traps.SigNaN
RTS
SetExcept040
FNOP ; Ensure the 040 FP is idle
MOVE.L A0,D1 ; Copy exceptions into D1
FMOVE.L FPSR,D0 ; D0 <- FPSR
AND.W #$00FF,D0 ; Clear previous op flags <5/12/90-S.McD.>
OR.W D1,D0 ; Set proper exceptions
FMOVE.L D0,FPSR ; Move results back to FPSR
FMOVE.L FPCR,D0 ; D0 <- FPCR
AND.W D0,D1 ; Find exception intersection
ANDI.L #$FF00,D1 ; Mask off low byte and high word
BNE.S @1 ; Force vectoring to highest priority exception handler
RTS ; Return if none enabled
@1:
BTST #15,D1 ; BSUN handler?
BEQ.S @2 ; No
FMOVE.S #"$7FFFFFFF",FP1 ; Yes; set NaN condition code
FBGT.W @done ; BSUN set on unordered branch condition
FNOP
RTS
@2:
BTST #14,D1 ; SNaN?
BEQ.S @3 ; No
FCMP.S #"$7FBFFFFF",FP1 ; Yes; compare FP1 with signaling NaN
BRA.S @done
@3:
BTST #13,D1 ; Operror?
BEQ.S @4 ; No
FMOVE.S #"$7F800000",FP1 ; Yes; do INF - INF
FSUB.X FP1,FP1
BRA.S @done
@4:
BTST #12,D1 ; Overflow?
BEQ.S @5 ; No
FMOVE.S #"$7F000000",FP1 ; Yes; load large single-precision value
FSMUL.X FP1,FP1 ; and square it
@done:
FNOP ; Flush pending exceptions
RTS ; Return
@5:
BTST #11,D1 ; Underflow?
BEQ.S @6 ; No
FMOVE.S #"$1F000000",FP1 ; Yes; load small single-precision value
FSMUL.X FP1,FP1 ; and square it (result is subnormal/exact)
BRA.S @done
@6:
BTST #10,D1 ; Divide-by-zero?
BEQ.S @7 ; No. Inexact
FMOVE.B #1,FP1 ; Yes; divide 1.0 by 0.0
FDIV.B #0,FP1
BRA.S @done
@7:
FMOVE.B #1,FP1 ; 040 can trap only on INEX2 condition
FADD.S #"$00800000",FP1 ; add 1.0 to 2.0**-126
BRA.S @done
END