mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
0ba83392d4
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.
611 lines
18 KiB
Plaintext
611 lines
18 KiB
Plaintext
;EASE$$$ READ ONLY COPY of file ÒFP881nonarith.aÓ
|
||
; 1.2 GGD 07/14/1989 Fixed CopySign to copy Sign(dst) -> Sign(src), even though it seems
|
||
; backwards, that is how it is documented, and how the Mac Plus/SE work.
|
||
; 1.1 CCH 11/11/1988 Fixed Header.
|
||
; 1.0 CCH 11/ 9/1988 Adding to EASE.
|
||
; OLD REVISIONS BELOW
|
||
; 1.0 BBM 2/12/88 Adding file for the first time into EASEÉ
|
||
; END EASE MODIFICATION HISTORY
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; File: FP881nonarith.a
|
||
;; Implementation of FP68K non-arithmetic functions.
|
||
;; Copyright Apple Computer, Inc. 1985,1986,1987
|
||
;; All Rights Reserved
|
||
;; Confidential and Proprietary to Apple Computer,Inc.
|
||
;;
|
||
;; Written by Clayton Lewis, begun 14 Feb 85.
|
||
;; Debugged by Stuart McDonald.
|
||
;;
|
||
;; Modification history:
|
||
;; Rev2: 16 May 85
|
||
;; Rev3: 17 May 85
|
||
;; Rev4: 17 May 85
|
||
;; Rev5: 27 May 85
|
||
;; Rev6: 30 May 85
|
||
;; Rev7: 04 Jun 85
|
||
;; Rev8: 16 Jun 85 CRL moved to MPW
|
||
;; Rev9: 08 Sep 86 -S.McD. Minor revs. to NextAfter to handle NaNs and SNaNs
|
||
;; RevA: 19 Nov 86 -S.McD. Fixed TestExp's case selection.
|
||
;; 26 Dec 86 -S.McD. CopySign rearranged slightly.
|
||
;; 28 Dec 86 -S.McD. Fixed ProcEx's behavior.
|
||
;; 30 Dec 86 -S.McD. Zeroed FPSR for NonArith codes exiting thru halt check.
|
||
;; 03 Jan 87 -S.McD. Nextafter was signalling on old status.
|
||
;; 13 Jan 87 -S.McD. Now save/restore any of the registers FP2-FP7 used.
|
||
;; 15 Jan 87 -S.McD. Status and copyright notice changed.
|
||
;; 21 Jan 87 -S.McD. Cleaned up SetHv/GetHv.
|
||
;; 22 Jan 87 -S.McD. SetExp was setting halt bit instead of flag bit.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
ToSANE ; used by EGet below and by halt mechanism in FP881Arith
|
||
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
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; GET ENVIRONMENT.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
GetEnv
|
||
BSR.S EGet ; returning SANE Env in D1
|
||
MOVEA.L LKADR1(A6),A1
|
||
MOVE.W D1,(A1)
|
||
BRA Exit1NoHalt
|
||
|
||
EGet
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Used by GetEnvironment, ProcEntry.
|
||
;; Returns SANE environment in D1.
|
||
;; D5.hi = STATUS.lo; D5.lo = CONTROL
|
||
;; -----------------------------------------
|
||
;; First transfer accrued exceptions to D1.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEQ #19,D1 ; clear result space
|
||
|
||
MOVE.L D5,D0
|
||
LSR.L D1,D0 ; move exceptions to low bits
|
||
ANDI.W #XCPMASK,D0 ; mask word to only 5 bits
|
||
MOVE.B ToSANE(PC,D0),D1 ; set SANE exception bits
|
||
LSL.W #8,D1 ; and move to high byte
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Move CONTROL to the stack and map the eight
|
||
;; 881 halt bits to 5 SANE bits in D1.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.W D5,-(SP) ; copy of caller control register
|
||
|
||
MOVE.B (SP),D0 ; pick up only the halt bits
|
||
LSR.B #1,D0 ; shift I1 to carry bit
|
||
BCC.S @1 ; branch if I1 not set
|
||
ORI.B #1,D0 ; else copy I1 to I2 as lowest bit
|
||
@1
|
||
CMPI.B #$10,D0 ; are any of the 3 invalid bits set?
|
||
BCS.S @2 ; if not, branch
|
||
BSET #0,D1 ; else set invalid in D1
|
||
@2
|
||
ANDI.W #$0F,D0 ; show only OUDI bits
|
||
OR.B ToSANE(PC,D0),D1 ; set corresponding SANE halts
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Collect and set in D1 first RR (rounding precision)
|
||
;; bits then rr (rounding direction) bits.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.W #$C0,D0
|
||
AND.W (SP),D0 ; show only RR bits of CONTROL
|
||
ROL.B #2,D0 ; RR to low bits
|
||
OR.B RPrec(PC,D0),D1 ; set RR in D1
|
||
|
||
MOVEQ #$30,D0 ; mask for rr bits
|
||
AND.W (SP)+,D0 ; collect rr bits; pop temp from stack
|
||
LSR.B #3,D0 ; move to bits 1 & 2 (index to a WORD table)
|
||
OR.W rDir(PC,D0),D1 ; set rr in D1
|
||
RTS
|
||
RPrec
|
||
DC.B 0,64,32,0
|
||
rDir
|
||
DC.W 0,24576,16384,8192
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; SET ENVIRONMENT.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
SetEnv
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Move SANE environment to D0, convert to
|
||
;; 881 format, set environment, and exit.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEA.L LKADR1(A6),A1
|
||
MOVE.W (A1),D0
|
||
BSR.S ESet ; sets SANE Env currently in D0
|
||
BRA Exit1NoHalt
|
||
ESet
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Used by SetEnv, ProcExit, SetException.
|
||
;; Enter with D0 holding SANE environment to be set.
|
||
;; Routine sets equivalent environment in D5 for later pass to 881.
|
||
;; -----------------------------------------------------
|
||
;; Install the exception bits in the 881 STATUS register.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.W D0,-(SP) ; keep a copy of env on the stack
|
||
MOVEQ #XCPMASK,D0 ; mask for 5 exception bits
|
||
AND.B (SP),D0 ; capture exception bits
|
||
|
||
FMOVE FPSR,D1
|
||
|
||
MOVE.B FromSANE(PC,D0),D1 ; map to 881 accrued exceptions
|
||
|
||
; and install in 881
|
||
FMOVE D1,FPSR
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Collect halt bits in D0. Duplicate hi bit 3 times and
|
||
;; low bit twice to set all 3 invalid and 2 inexact halts.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEQ #XCPMASK,D0 ; show only 5 halt bits
|
||
AND.W (SP),D0
|
||
MOVE.B FromSANE(PC,D0),D0 ; halts in hi bits of byte
|
||
ASR.B #2,D0 ; replicate the hi bit twice
|
||
LSL.W #6,D0 ; shift all but lowest bit to hi byte
|
||
ASR.B #1,D0 ; replicate the low bit once
|
||
LSL.W #2,D0 ; and shift all bits to hi byte
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Set rr (rounding direction) bits in D0.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEQ #0,D1 ; clear D1 for indexing below
|
||
MOVE.B #3,D0 ; mask and shift count
|
||
MOVE.B (SP),D1 ; fresh copy of SANE environment
|
||
ROL.B D0,D1 ; move rr to low bits
|
||
AND.B D0,D1 ; and mask to show only rr
|
||
MOVE.B rrDir(PC,D1),D0 ; map to 881 rr bits
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Set RR (rounding precision) bits in D0 and reset control in D5.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEQ #$60,D1
|
||
AND.W (SP)+,D1 ; mask to RR and pop saved env from stack
|
||
ROL.B #3,D1 ; shift to low bits
|
||
OR.B RRPrec(PC,D1),D0 ; map to 881 RR bits
|
||
MOVE.W D0,D5 ; reset user control held in D5
|
||
RTS
|
||
FromSANE
|
||
DC.B 0,128,32,160,64,192,96,224
|
||
DC.B 16,144,48,176,80,208,112,240
|
||
DC.B 8,136,40,168,72,200,104,232
|
||
DC.B 24,152,56,184,88,216,120,248
|
||
RRPrec
|
||
DC.B 0,128,64,0
|
||
rrDir
|
||
DC.B 0,48,32,16
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; SET HALT VECTOR & GET HALT VECTOR.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
SetHv
|
||
MOVE.L #FPSTATE+2,A0
|
||
MOVE.L LKADR1(A6),A1
|
||
MOVE.L (A1),(A0)
|
||
BRA Exit1NoHalt
|
||
|
||
GetHv
|
||
MOVE.L #FPSTATE+2,A0
|
||
MOVE.L LKADR1(A6),A1
|
||
MOVE.L (A0),(A1)
|
||
BRA Exit1NoHalt
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; NEGATE.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
Negate
|
||
MOVE.L LKADR1(A6),A0
|
||
BCHG.B #7,(A0)
|
||
BRA Exit1NoHalt
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; ABSOLUTE VALUE.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
Abs
|
||
MOVE.L LKADR1(A6),A0
|
||
BCLR.B #7,(A0)
|
||
BRA Exit1NoHalt
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; PROCENTRY.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
ProcEnt
|
||
BSR EGet ; SANE env now in D1
|
||
MOVE.L LKADR1(A6),A0
|
||
MOVE.W D1,(A0)
|
||
|
||
MOVEQ #0,D5 ; set environment 0
|
||
|
||
FMOVE D5,FPSR
|
||
|
||
BRA Exit1NoHalt
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; TESTEXCEPTION.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
TestExp
|
||
MOVE.L LKADR1(A6),A0
|
||
MOVE.W (A0),D1 ; was .L -S.McD.
|
||
MACHINE MC68020
|
||
MOVE.W IndTab(PC,D1*2),D1 ; added *2. -S.McD.
|
||
MACHINE MC68000
|
||
CLR.W (A0)
|
||
BTST D1,D5
|
||
BEQ.S @2
|
||
ADDQ.B #1,(A0)
|
||
@2
|
||
BRA Exit1NoHalt
|
||
|
||
IndTab
|
||
DC.W 23,21,22,20,19 ; not 22,21. -S.McD.
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; NEXTAFTER - Modify SRC by one ulp in direction of DST
|
||
;; 1. Clear the control register (default rounding, no halts) and
|
||
;; move the tiniest extended denorm to FP2.
|
||
;; 2. Move SRC to FP0. If INF bit is set, then set SRCINF flag and save sign bit.
|
||
;; 3. Move DST to FP1. If NaN bit is set, then move FP1 to FP0.
|
||
;; 4. Compare FP0 and FP1. If equal, then go to 9.
|
||
;; 5. If SRC = Infinity, handle separately, returning INF dec 1.
|
||
;; If FP1 > FP0 then set rounding to upward, & add tiniest denorm to FP0
|
||
;; else set rounding downward, & subt tiniest denorm from FP0.
|
||
;; Test for 0 result. If found, change sign.
|
||
;; 6. Move result from FP0 to SRC and check for INF. Skip 7 if not found.
|
||
;; 7. INF returned. If SRCINF is not set, then set [ovfl, inex] locally.
|
||
;; 8. Check opcode for format of SRC and examine exponent manually for zero or
|
||
;; denorm. If either, then set [underflow, inexact] locally.
|
||
;; 9. Pass local exception flags to 881. Exit through halt checking code
|
||
;; (which acts like procexit; restoring caller's environment, stimulating
|
||
;; current exceptions, and possibly halting).
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
NextAfter
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 1. Clear the control register and move the tiniest extended denorm to FP2
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
FMOVE #0,FPCR
|
||
FMOVEM FP2,-(SP) ; must save/restore FP2-FP7 -S.McD.
|
||
FMOVE.X #"$000000000000000000000001",FP2
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 2. Move SRC to FP0.
|
||
;; If INF bit is set, then set SRCINF flag, handle INF and goto 6.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.L LKADR2(A6),A0 ; collect source address
|
||
MOVEQ #19,D0
|
||
EOR.W D0,D1 ; leave only format in opword
|
||
ROL.W #4,D1 ; D-bit to bit 15, S-bit to bit 0. Other bits zero.
|
||
BNE.S @2 ; branch if single or double
|
||
|
||
ADDQ.L #6,A0 ; Extended SRC
|
||
MOVE.L (A0),-(SP)
|
||
MOVE.L -(A0),-(SP)
|
||
SUBQ.L #2,A0
|
||
MOVE.L (A0),-(SP)
|
||
|
||
FMOVE.X (SP)+,FP0
|
||
|
||
BRA.S @6
|
||
@2
|
||
BPL.S @4 ; branch if single
|
||
|
||
FMOVE.D (A0),FP0 ; Double SRC
|
||
|
||
BRA.S @6
|
||
@4
|
||
FMOVE.S (A0),FP0 ; Single SRC
|
||
@6
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Test SRC for INF or SNaN
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
FMOVE FPSR,D0
|
||
|
||
BTST #14,D0 ; is SNaN bit set from SRC move?-S.McD.
|
||
BEQ.S @7 ; if not, skip to INF tests
|
||
BSET #29,D1 ; else save SNaN bit in D1 and
|
||
BRA.W State6 ; begin returning Nan
|
||
@7
|
||
BTST #25,D0 ; is INF bit set from SRC move?
|
||
BEQ.S State3 ; if not, skip flag setting
|
||
BSET #31,D1 ; else set SRCINF flag in D1
|
||
|
||
BTST #27,D0 ; what sign infinity?
|
||
BEQ.S State3 ; branch if positive
|
||
BSET #30,D1 ; save sign bit in D1
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 3. Move DST to FP1.
|
||
;; If NaN bit is set, then move FP1 to SRC.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State3
|
||
MOVE.L LKADR1(A6),A1 ; collect destination address
|
||
TST.W D1
|
||
BNE.S @8 ; branch if single or double format
|
||
|
||
ADDQ.L #6,A1 ; Extended DST
|
||
MOVE.L (A1),-(SP)
|
||
MOVE.L -(A1),-(SP)
|
||
SUBQ.L #2,A1
|
||
MOVE.L (A1),-(SP)
|
||
|
||
FMOVE.X (SP)+,FP1
|
||
|
||
BRA.S @12
|
||
@8
|
||
BPL.S @10 ; branch if single
|
||
|
||
FMOVE.D (A1),FP1 ; Double DST
|
||
|
||
BRA.S @12
|
||
@10
|
||
FMOVE.S (A1),FP1 ; Single DST
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Move DST if NaN bit set
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
@12
|
||
FBOR.W State4 ; branch if NaN bit not set
|
||
FMOVE FP1,FP0 ; else DST was a NaN. Copy it to FP0.
|
||
BTST.B #6,2(A1) ; was that a SNaN?
|
||
BNE.S State6 ; if no, then State6
|
||
BSET #29,D1 ; if yes, use bit 29 of D1 as temp SNaN flag
|
||
BRA.S State6 ; NaN result. Time to get out. -S.McD.
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 4. Compare FP0 and FP1. If equal, then go to state 9.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State4
|
||
FCMP FP0,FP1
|
||
FBNE.W State5
|
||
|
||
BRA State9
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 5. If SRC = Infinity, handle separately, returning INF dec 1.
|
||
;; If FP1 > FP0, then set rounding to upward & add FP2 to FP0
|
||
;; else set rounding to dwnwrd & sub FP2 fm FP0.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State5
|
||
TST.L D1 ; was source an infinity?
|
||
BGE.S @8 ; if not, branch around infinity code
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Infinity code.
|
||
;; INF = SRC DST, so result = Infinity decremented by 1.
|
||
;; Move this value to FP0.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVEQ #-1,D0 ; no exceptions to be OR'd in
|
||
TST.W D1
|
||
BNE.S @2 ; branch if single or double format
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle extended precision INF dec 1.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.W #$7FFE,(A0)+
|
||
MOVE.L D0,(A0)+
|
||
MOVE.L D0,(A0)
|
||
SUBQ #6,A0
|
||
BRA.S @6
|
||
@2
|
||
BPL.S @4 ; branch if single
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle double precision INF dec 1.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.L #$7FEFFFFF,(A0)+
|
||
MOVE.L D0,(A0)
|
||
SUBQ #4,A0
|
||
BRA.S @6
|
||
@4
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle single precision INF dec 1.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
MOVE.L #$7F7FFFFF,(A0)
|
||
@6
|
||
BTST #30,D1 ; sign of SRC?
|
||
BEQ.S @7 ; do nothing if positive
|
||
BSET #7,(A0) ; else set sign bit
|
||
@7
|
||
MOVEQ #0,D0 ; signal no exceptions
|
||
BRA State9 ; and leave
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Non-infinity code.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
@8
|
||
FBOGT.W @10 ; branch if FP1 > FP0
|
||
|
||
MOVEQ #$20,D0 ; set rounding downward
|
||
|
||
FMOVE D0,FPCR
|
||
FSUB FP2,FP0
|
||
|
||
BRA.S @12 ; branch if FP1 <? FP0
|
||
@10
|
||
MOVEQ #$30,D0 ; set rounding upward
|
||
|
||
FMOVE D0,FPCR
|
||
FADD FP2,FP0
|
||
@12
|
||
FBNE.W State6
|
||
FNEG FP0,FP0
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 6. Move result from FP0 to SRC.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State6
|
||
TST.W D1
|
||
BNE.S @2 ; branch if single or double format
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle extended precision.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
FMOVE.X FP0,-(SP) ; Extended DST
|
||
|
||
MOVE.L (SP)+,(A0)+
|
||
SUBQ.L #2,A0
|
||
MOVE.L (SP)+,(A0)+
|
||
MOVE.L (SP)+,(A0)
|
||
SUBQ.L #6,A0
|
||
|
||
FMOVE FPSR,D0 ; check INF
|
||
|
||
BTST #29,D1 ; is SNaN bit set? -S.McD.
|
||
BEQ.S @1 ; skip if not SNaN
|
||
MOVE.L #$80,D0 ; set invalid if SNaN
|
||
BRA.S State85
|
||
@1
|
||
BTST #25,D0 ; is INF bit set?
|
||
BEQ.S State8 ; State8 if not INF
|
||
BRA.S State7 ; State7 if INF
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle double precision.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
@2
|
||
BPL.S @4 ; branch if single
|
||
|
||
FMOVE.D FP0,(A0) ; Double DST
|
||
|
||
MOVE.L (A0),D0 ; examine hi long of double for INF
|
||
ADD.L D0,D0 ; ignore sign bit
|
||
CMPI.L #$FFE00000,D0 ; does it match INF?
|
||
BNE.S State8 ; State8 if no match
|
||
TST.L 4(A0) ; does lo long of double match INF?
|
||
BNE.S State8 ; State8 if not INF
|
||
BRA.S State7 ; State7 if INF
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; Handle single precision.
|
||
;;;;;;;;;;;;;;;;;;;;;;;
|
||
@4
|
||
FMOVE.S FP0,(A0) ; Single DST
|
||
|
||
MOVE.L (A0),D0 ; examine single for INF
|
||
ADD.L D0,D0 ; ignore sign bit
|
||
CMPI.L #$FF000000,D0 ; does it match INF?
|
||
BNE.S State8 ; branch if no match
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 7. INF returned. If SRCINF is not set, then set [ovfl, inex].
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State7
|
||
TST.L D1 ; check SRCINF flag at bit 31
|
||
BMI.S State8 ; if set, go to next state
|
||
MOVEQ #$48,D0 ; if INF ^ ~SRCINF then hold o,x in D0 for later
|
||
BRA.S State85
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 8. Check opcode for format of SRC and examine exponent
|
||
;; manually for zero or denorm. If either, then set [ufl, inex].
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State8
|
||
MOVEQ #0,D0
|
||
State85
|
||
TST.W D1
|
||
BNE.S @2 ; branch if single or double format
|
||
MOVE.W #$7FFF,D1 ; extended exponent mask
|
||
TST.B 2(A0) ; test the 'i' bit in extended format
|
||
BMI.S State9 ; if set, then cannot be denormal.BNE->BMI-S.McD.
|
||
BRA.S @6
|
||
@2
|
||
BPL.S @4 ; branch if single
|
||
MOVE.W #$7FF0,D1 ; double exponent mask
|
||
BRA.S @6
|
||
@4
|
||
MOVE.W #$7F80,D1 ; single exponent mask
|
||
@6
|
||
AND.W (A0),D1 ; exactly the exponent bits
|
||
BNE.S State9 ; if nonzero, then neither zero nor denorm
|
||
MOVEQ #$28,D0 ; if exponent=0 then hold u,x for later
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; State 9. Pass local exception flags to 881. Exit thru common code.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
State9
|
||
MOVEQ #0,D1 ; zero status -S.McD.
|
||
MOVE.W D0,D1 ; set exceptions from above -S.McD.
|
||
|
||
FMOVE D1,FPSR
|
||
FMOVEM (SP)+,FP2 ; must save/restore FP2-FP7 -S.McD.
|
||
|
||
BRA Exit2Args
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; PROCEXIT
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
ProcEx
|
||
FMOVE FPSR,D1 ; get current status -S.McD.
|
||
MOVE.W D1,A1 ; and save it temporarily in A1. -S.McD.
|
||
|
||
MOVE.L LKADR1(A6),A0 ; addr saved environment
|
||
MOVE.W (A0),D0 ; saved environment
|
||
BSR ESet ; SANE env in D0 -> FPSR:FPCR in D5
|
||
|
||
MOVEQ #STKREM1,D0 ; unrolled Exit1Arg to handle special D1. -S.McD.
|
||
LEA LKADR1(A6),A0
|
||
MOVE.W D0,LKCNT(A6) ; final stack adjust
|
||
|
||
MOVE.W A1,D1 ; restore current status to D1. -S.McD.
|
||
FMOVE FPSR,D0 ; "or" in current status with saved status. -S.McD.
|
||
OR.W D1,D0
|
||
FMOVE D0,FPSR
|
||
|
||
SWAP D5 ; ExitProcEx expects FPSR and FPCR swapped. -S.McD.
|
||
BRA ExitProcEx ; -S.McD.
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; SETEXCEPTION
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
SetExp
|
||
FMOVE #0,FPSR ; IEEE default status -S.McD.
|
||
MOVE.L LKADR1(A6),A0
|
||
BSR EGet ; returns SANE environment in D1
|
||
MOVE.W (A0),D0 ; bit index of exception to be set
|
||
ADDQ.W #8,D0 ; Set flag, not halt bit! -S.McD.
|
||
BSET D0,D1 ; set the exception
|
||
MOVE.W D1,D0 ; new SANE environment
|
||
SetOut
|
||
BSR ESet ; place in 881
|
||
BRA Exit1Arg ; and exit through halt testing code
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; COPYSIGN.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
CopySign
|
||
MOVE.L LKADR1(A6),A0
|
||
MOVE.L LKADR2(A6),A1
|
||
|
||
; This code is opposite from the MacSE, should copy dst->src
|
||
* BCLR #7,(A0) ; <1.2>
|
||
* TST.B (A1) ; <1.2>
|
||
* BPL.S Exit2NoHalt ; <1.2>
|
||
* BSET #7,(A0) ; <1.2>
|
||
|
||
; CopySign is documented as Sign(dst) -> Sign(src)
|
||
move.w (a0),d0 ; get dst sign into bit 15 <1.2>
|
||
move.b (a1),d0 ; get src sign into bit 8 <1.2>
|
||
add.w d0,d0 ; shift dst sign into carry <1.2>
|
||
roxr.b #1,d0 ; shift dst sign into src <1.2>
|
||
move.b d0,(a1) ; restore updated src sign <1.2>
|
||
|
||
Exit2NoHalt
|
||
MOVEQ #STKREM2,D0
|
||
MOVE.L LKRET(A6),LKADR2(A6)
|
||
BRA.S AndOut
|
||
|
||
Exit1NoHalt
|
||
MOVEQ #STKREM1,D0
|
||
MOVE.L LKRET(A6),LKADR1(A6)
|
||
|
||
AndOut
|
||
MOVE.W D0,LKCNT(A6)
|
||
|
||
MOVE.W D5,D0 ; rest of D0 zeroed by MOVEQs. -S.McD.
|
||
FMOVE D0,FPCR ; restore control register from D0, which may
|
||
; have been modified by ESet or ProcEntry
|
||
|
||
MOVEA.L (A6),A6
|
||
MOVEM.L (SP)+,D0/D1/D5/A0/A1
|
||
ADDA.W (SP),SP
|
||
RTS
|
||
|