mac-rom/Toolbox/InSANE/HWElemsControl.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

433 lines
16 KiB
Plaintext

;
; File: HWElemsControl.a
;
; Contains: HW Floating Point ELEMS68K ("PACK 5") that calls MC68881/882 or uses MC68040 FPU
;
; Written by: Apple Numerics Group, DSG
;
; Copyright: © 1985-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM2> 2/3/92 CSS Update from Horror: see mod history from below 06 Apr 92, 08 Apr 92.
; <2> 11/2/91 DTY Put the End after the EndIf.
; <1> 10/24/91 SAM/KSM Rolled in Regatta file.
;
; Regatta Change History:
;
; <2> 5/28/91 SAM Merged from TERROR sources. [<2> Fixed a bug in ANNUITY and
; COMPOUND that used to allow the possibility of spuriously
; signaling an invalid exception under reasonable circumstances.
; <1> 5/15/91 SAM Split off from TERROR Proj.
;
; Terror Change History:
;
; <1> 01/06/91 BG Added to TERROR/BBS for the time.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File: 881Elemscontrol.a
;; Implementation of Elems68K for machines using the Motorola 68881/2
;; Copyright Apple Computer, Inc. 1985-7,1989-92
;; All Rights Reserved
;; Confidential and Proprietary to Apple Computer,Inc.
;;
;; Written by Clayton Lewis, from the (unshipped) file ChipElems881.a
;;
;; Modification history:
;; Rev1: 17 May 89 Resurrection from ChipElems881.a begins.
;; 25 Sep 90 96-bit test for tiny fixed; version updated. -SMcD
;; 01 Oct 90 made MAIN & END conditional assembly for ROM & INIT ... ali
;; 01 Oct 90 chnaged the label STICKMAP to STICKYMAP2 to avoid
;; collision with pack 4's STICKYMAP ... ali
;; 05 Oct 90 merged SMcDÕs conditional assembly scheme for
;; ÔMAIN ... ENDÕ pair
;; 05 Apr 91 for financial functions only, a jump over the first argument
;; fetch was added. thanks to jon okada for patiently single
;; stepping to find the problem. ... ali
;; 06 Apr 92 changed version number to 9, updated copyright dates. ... JPO
;; 08 Apr 92 used FMOVEM to move result in FP0 to memory. ... JPO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The stack looks like:
;; _______________________________________________
;; | |
;; | address of argument 3 (if any) | - Long
;; |_______________________________________________|
;; | |
;; | address of argument 2 (if any) | - Long
;; |_______________________________________________|
;; | |
;; | address of argument 1 | - Long
;; |_______________________________________________|
;; | |
;; | opcode (NOTE: change to bit 7 !!!) | - Word
;; |_______________________________________________|
;; | |
;; | return address | - Long
;; |_______________________________________________|
;;
;; The number of addresses depends on the operation. xpwri and xpwry use 2.
;; compound and annuity use 3. All the rest use only 1.
;;
;; Opcode - If bit 7 is set, all extended data must be in 96-bit format.
;; If bit 7 is clear, all extended data must be in 80-bit format.
;;
;; Save registers D0/D1 & A0/A4 & FP2/FP3, and later save FPSR and FPCR.
;;
;; | |
;; | stack as passed |
;; |_______________________________________________|
;; | |
;; | saved D0/D1 & A0/A4 & FP2/FP3 | - 10 Longs
;; |_______________________________________________|
;; | |
;; | saved FPSR | - Long
;; |_______________________________________________|
;; | |
;; | saved FPCR | - Long
;; |_______________________________________________|
;;
;; Conventions - routines getting control through this file may assume:
;;
;; ¥ A0 contains the address of the input argument
;; ¥ A4 contains the address of the exit routine - to exit, use: JMP (A4)
;; ¥ FP0 contains the input argument itself
;; ¥ D0 & D1 are junk from routine dispatch
;; ¥ FP0 must contain the result value for delivery to common exit routines
;; ¥ routines must exit with stack unchanged!!!
;; ¥ xpwri, xpwry, compound, annuity are special cases handling own data and exit
;; ¥ Preserved registers are listed in HWElemsEqus.a
;; ¥ Routines which must know whether data is 80-bit or 96-bit can test bit 7
;; of the opcode which is at Opcode+1(SP) immediately after dispatch.
;;
;; Except - no registers are preset for annuity and compound.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IF &TYPE('InitMe') = 'UNDEFINED' THEN ; to make ½SANE an INIT, MAIN & END must be
MAIN ; commented out. they are necessary for the
ENDIF ; the ROM built. ( and also regular testing )
BLANKS ON
STRING ASIS
; DATA MAIN
; ORG -$100
CODE
PRINT ON
MACHINE MC68020
MC68881
INCLUDE 'HWElemsEqus.a'
FPState EQU $A4A ; floating point state [6 bytes]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;This is the sole entry point of the package.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT ELEMS881
ELEMS881
; IF DebugON THEN
; DC.W $A9FF
; ENDIF
BRA.S Elemsbegin
DC.W $00 ; MAC SPECIFIC STUFF
STRING ASIS
DC.B 'PACK'
DC.W $5
DC.W $0009 ; VERSION 9 <4/6/92, JPO>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Beginning of code.
;; Reserve space, save registers, execute procentry, and dispatch to called routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Elemsbegin
MOVEM.L Regs,-(SP) ; save working registers
FMOVEM FPRegs,-(SP)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ProcEntry
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FMOVE.L FPSR,-(SP) ; Save status register (high memory)
FMOVE.L FPCR,-(SP) ; and control register (low memory)
MOVEQ #0,D1
FMOVE.L D1,FPCR ; IEEE default rounding, precision, halts
FMOVE.L D1,FPSR ; clear exceptions (condition code and Quo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Move the (extended) destination value to the chip and select appropriate
;; exit sequence. If it is a financial function, then skip the first fetch <T2>
;; since it is going to be a destination for the financials. <T2>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVEA.L Addr1(SP),A0 ; destination address in A0
; MOVE.B Opcode+1(SP),D0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <T2> thru next <T2>
;; Added this section to handle financials separately. For these functions the
;; first argument is a destination and at the start may hold garbage including
;; SNaN. For the 68040, it may slow down the financials since the garbage may
;; be an unnormalized number, which will trap to the software... ali
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVE.W Opcode(SP),D0 ; grab the entire opword
BTST #IsItFinan,D0 ; high byte of opword is $C0 if financial
BEQ.S @2 ; if not, go get the first operand
BTST #flag96bit,D0 ; it is a financial, find out if 80 or 96 bit
BEQ.S @3 ; branch to unpack 80-bit input data
LEA Out96,A4 ; else just take 96-bit input data
BRA.S LiftOff
@3
LEA Out80,A4
BRA.S LiftOff
@2
BTST #flag96bit,D0 ; if not continue, find out if 80 or 96 bit
BEQ.S @1 ; branch to unpack 80-bit input data
; BPL.S @1 ; branch to unpack 80-bit input data
MOVE.W 4(A0),2(A0) ; replicate significant word into junk word <9/25/90-S.McD>
LEA Out96,A4 ; else just take 96-bit input data <T2>
FMOVE.X (A0),FP0
BRA.S LiftOff
@1
LEA Out80,A4
ADDQ.L #6,A0
MOVE.L (A0),-(SP)
MOVE.L -(A0),-(SP)
SUBQ.L #2,A0
MOVE.L (A0),-(SP)
FMOVE.X (SP)+,FP0
LiftOff
MOVE.W #OPMASK,D1
AND.B D0,D1
MOVE.W ElemsTab(D1),D1
JMP LiftOff(D1)
ElemsTab
DC.W RLnx-LiftOff
DC.W RLog2x-LiftOff
DC.W RLn1x-LiftOff
DC.W RLog21x-LiftOff
DC.W RExpx-LiftOff
DC.W RExp2x-LiftOff
DC.W RExp1x-LiftOff
DC.W RExp21x-LiftOff
DC.W RXpwri-LiftOff
DC.W RXpwry-LiftOff
DC.W RCompound-LiftOff
DC.W RAnnuity-LiftOff
DC.W RSin-LiftOff
DC.W RCos-LiftOff
DC.W RTan-LiftOff
DC.W RAtan-LiftOff
DC.W RRandom-LiftOff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Exit code
;; All one argument routines exit through here
;; A4 contains the address of the appropriate exit routine (80 or 96-bit extended)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Out80
MOVEA.L Addr1(SP),A0 ; destination address in A0
; FMOVE.X FP0,-(SP) ; move result to stack - DELETED <4/8/92, JPO>
FMOVEM.X FP0,-(SP) ; move result to stack <4/8/92, JPO>
MOVE.W (SP)+,(A0)+ ; move result to memory
ADDQ.L #2,SP
MOVE.L (SP)+,(A0)+
MOVE.L (SP)+,(A0)
BRA.S Exit
Out96
MOVEA.L Addr1(SP),A0 ; destination address in A0
; FMOVE.X FP0,(A0) ; deliver result - DELETED <4/8/92, JPO>
FMOVEM.X FP0,(A0) ; deliver result <4/8/92, JPO>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Adjust the pending exceptions
;; D0.hi MUST contain set bits for each exception to be set
;; D0.lo MUST contain set bits for each exception to be cleared
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Exit
MOVEQ #-1,D1 ; set mask
EOR.B D1,D0 ; exception bits to be cleared now in D0.lo
FMOVE FPSR,D1 ; collect current exceptions
AND.B D0,D1 ; clear unwanted exceptions
SWAP D0 ; exceptions to be set now in D0.lo
OR.B D1,D0 ; set desired exceptions
*
* The next step is handled in the Procexit code below, so it is commented out.
* FMOVE D0,FPSR ; record pending exceptions from this "operation"
*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Procexit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*
* This is a private PROCEXIT for ½SANE881's PACK5. Since all
* elementary function exceptions are triggered by PROCEXIT,
* PROCEXIT is blamed for all of PACK5's exceptions.
*
* This code performs the halt mechanism steps discussed on p.168
* of the Apple Numerics Manual, Second Edition. Figure 23-1
* (Stack frame for halt), p.169, is quite helpful.
*
* This code was written to be as independent as possible from PACK4.
* ½SANE881 PACK5 will run stand-alone without ½SANE881 PACK4 being present
* except because ½SANE881 PACK4 always runs with OPERR trapping enabled,
* the user's invalid halt enable is stored as (BSUN or SNAN), where BSUN,
* SNAN, and OPERR are, respectively, the three high bits of the eight FPU
* trap enables. See Figure 2-2 (MC68881/MC68882 FPCR Exception Enable Byte),
* p.2-2, in Motorola's 881/2 Manual.
*
* That is, halt on invalid is enabled if and only if BSUN or SNAN is set in FPCR.
*
* OPERR trapping is assumed enabled so PACK4 can override the FPU's default
* return behavior for operand errors, i.e. so PACK4 can deliver SANE's style
* of floating-point and integer NaN codes.
*
* BEFORE:
* STACK: FPCR< FPSR< D0_D1/A0_A4/FP2_FP3< RTS< opcode< &DST< &SRC< &SRC2
*
* AFTER:
* STACK: D0_D1/A0_A4/FP2_FP3< RTS< opcode< &DST< &SRC< &SRC2
*
* SIDE-EFFECT: Signals the accrued exceptions currently set on the FPU
* after restoring the saved FPCR & FPSR values on the stack.
*
* SCRATCHED: A0, D0, D1.
*
OR.B D0,7(SP) ; 'or' in stickies into saved FPSR on stack
MOVE.B 2(SP),D1 ; d1.b := saved FPCR trap enables byte
FMOVEM (SP)+,FPCR/FPSR ; restore saved environment (cc not affected)
*
* Since OPERR is always enabled, the following branch will never be taken,
* so it is commented out.
* BEQ.S PastHalter ; trap enables all zero? then skip haltcheck
*
BCLR #5,D1 ; prepare to map invalid enable onto OPERR bit
BFTST D1{24:2} ; bsun or snan set? (invalid halt enabled?)
BEQ.S @1 ; if not, leave OPERR bit clear
BSET #5,D1 ; otherwise, set OPERR bit
@1:
AND #%00111110,D1 ; any halts enabled? (ignores INEX1 for BCD)
; (note: clears high-byte of d1.w for mask)
BEQ.S PastHalter ; if none enabled then skip halt check
LSL.B #2,D1 ; left justify halt enables in byte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Halt check.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
AND D1,D0 ; d0.b := any halt-enable intersections?
; (note: clears high-byte of d0.w)
BEQ.S PastHalter ; if no intersections, skip halt code
LSR.B #3,D0 ; d0.w := 5 intersection bits right justified
HaltCode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make the FP68K halt stack frame.
;; Save & restore A0 (end of stack frame ptr).
;; Set up stack frame:
;; ------------------
;; Pending D0 - long
;; -----------------
;; Pending CCR - word
;; ------------------
;; halts&xcps - word < ----
;; ------------------ ^
;; MISC rec ptr ----------->
;; ------------------
;; SRC2 addr - long
;; ------------------
;; SRC addr - long
;; ------------------
;; DST addr - long
;; ------------------
;; opcode - word
;; ------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CLR.L -(SP) ; push bogus pending D0 for PROCEXIT
CLR.W -(SP) ; push bogus pending CCR for PROCEXIT
MOVE.B STICKYMAP2(D0),D0 ; d0.w := halts&xcps mapped to SANE order
MOVE.W D0,-(SP) ; push Halt exceptions (note: high-byte clear)
MOVE.L SP,-(SP) ; push pointer to stuff now on stack (MISC REC)
MOVE.L Addr3-8+4+2+2+4(SP),-(SP) ; push &SRC2
MOVE.L Addr2-8+4+2+2+4+4(SP),-(SP) ; push &SRC
MOVE.L Addr1-8+4+2+2+4+4+4(SP),-(SP) ; push &DST
MOVE.W Opcode-8+4+2+2+4+4+4+4(SP),-(SP) ; push ELEM's Opcode
BSET #7,(SP) ; make it distinguishable from all FP Opcodes
MOVEA.L #FPState+2,A0
MOVEA.L (A0),A0 ; haltvector
JSR (A0) ; call user's halt routine
; user pops halt frame
ADDQ #8,SP ; we pop misc rec
PastHalter
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Stack cleanup and return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FMOVEM (SP)+,FPRegs
MOVEM.L (SP)+,Regs ; restore registers
RTD #6 ; return, leaving stack clear
STICKYMAP2: ; maps FPU's 5 accrued bits to SANE order
; SANE's bits read backwards with OVFL<-->UNFL
DC.B 0,16,8,24,2,18,10,26,4,20,12,28,6,22,14,30
DC.B 1,17,9,25,3,19,11,27,5,21,13,29,7,23,15,31
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Here is an alternative way of producing the random number ( following the ;;
;; same algorithm ). This method allows the operations to be carried out ;;
;; all in the integer domain, which is good; that is for now. The bad news ;;
;; is that the old method is still the more efficient way of computing the ;;
;; random function on a 68040! sorry. ... ali, received from crl and stu. ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; seed: d0
;; d1 <- random
;; MULU.L #16807,D1:D0
;; DIVU.L #$7FFFFFFF,D1:D0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions of one argument
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RRandom
FMUL.W #16807,FP0 ; 7^5 * x
MOVEQ #0,D0 ; report no exceptions
FMOVE.L #RANDMODULUS,FP1 ; 2^31-1
FREM FP1,FP0 ; (7^5 * x) rem (2^31-1)
FBGE.W @1 ; branch if positive
FADD FP1,FP0 ; else add 2^31-1 to make positive
@1
JMP (A4)
INCLUDE 'HWElemsExp.a'
INCLUDE 'HWElemsFinancial.a'
INCLUDE 'HWElemsCommon.a'
INCLUDE 'HWElemsLogs.a'
INCLUDE 'HWElemsTg.a'
INCLUDE 'HWElemsArcTg.a'
INCLUDE 'HWElemsSinCos.a'
INCLUDE 'HWElemsCoeffs.a'
IF &TYPE('InitMe') = 'UNDEFINED' THEN ; to make ½SANE an INIT, MAIN & END must be
; Why include a whole file to execute one pseudo-op? Seems kinda silly, doesn't it?
; INCLUDE '881ELEMSend.a' ; commented out. they are necessary for the
ENDIF ; the ROM built. ( and also regular testing )
END