mac-rom/Toolbox/InSANE/FPPrivTrap.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +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