mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
4325cdcc78
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.
785 lines
19 KiB
Plaintext
785 lines
19 KiB
Plaintext
;
|
|
; File: Util.a
|
|
;
|
|
; Contains: 040 FPU Emulation Package utility routines
|
|
;
|
|
; Originally Written by: Motorola Inc.
|
|
; Adapted to Apple/MPW: Jon Okada
|
|
;
|
|
; Copyright: © 1990, 1991 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; This file is used in these builds: Mac32
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <3> 5/24/91 BG Modified routine "ovf_r_k" to correctly round overflow results
|
|
; of FSMOVE, FDMOVE, FSABS, FDABS, FSNEG, and FDNEG for
|
|
; unnormalized input of large magnitudes.
|
|
; <2> 3/30/91 BG Rolling in Jon Okada's latest changes.
|
|
; <1> 12/14/90 BG First checked into TERROR/BBS.
|
|
|
|
; util.a
|
|
|
|
; Based upon Motorola file 'util.sa'
|
|
|
|
; CHANGE LOG:
|
|
; 08 Jan 91 JPO Changed jump tables "tblovfl", "tblunf", and
|
|
; "pregdst" to contain 16-bit addresses relative
|
|
; to the respective table tops. Remove function
|
|
; 'get_fline' (calls to be done in-line).
|
|
; 15 Feb 91 JPO Modified routines "ovf_r_x2" and "g_rndpr" to
|
|
; set appropriate rounding precision for operations
|
|
; of form FSXXX and FDXXX. Both E1 and E3 cases
|
|
; are checked for these opclass 0/2 operations.
|
|
; 02 May 91 JPO Modified routine "ovf_r_k" to correctly round
|
|
; overflow results of FSMOVE, FDMOVE, FSABS, FDABS,
|
|
; FSNEG, and FDNEG for unnormalized input of large
|
|
; magnitudes.
|
|
;
|
|
|
|
*
|
|
* util.sa 3.1 12/10/90
|
|
*
|
|
* This file contains routines used by other programs.
|
|
*
|
|
* ovf_res: used by overflow to force the correct
|
|
* result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
|
|
* derivatives of this routine.
|
|
* get_fline: get user's opcode word
|
|
* g_dfmtou: returns the destination format.
|
|
* g_opcls: returns the opclass of the float instruction.
|
|
* g_rndpr: returns the rounding precision.
|
|
* reg_dest: write byte, word, or long data to Dn
|
|
*
|
|
*
|
|
* 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.
|
|
|
|
* UTIL IDNT 2,1 Motorola 040 Floating Point Software Package
|
|
|
|
|
|
|
|
*
|
|
* Final result table for ovf_res. Note that the negative counterparts
|
|
* are unnecessary as ovf_res always returns the sign separately from
|
|
* the exponent.
|
|
*
|
|
ALIGN 16 ;+inf
|
|
EXT_PINF dc.l $7fff0000,$00000000,$00000000,$00000000
|
|
* ;largest +ext
|
|
EXT_PLRG dc.l $7ffe0000,$ffffffff,$ffffffff,$00000000
|
|
* ;largest magnitude +sgl in ext
|
|
SGL_PLRG dc.l $407e0000,$ffffff00,$00000000,$00000000
|
|
* ;largest magnitude +dbl in ext
|
|
DBL_PLRG dc.l $43fe0000,$ffffffff,$fffff800,$00000000
|
|
* ;largest -ext
|
|
|
|
tblovfl: ; table MODIFIED <1/8/91, JPO>
|
|
dc.w EXT_RN-tblovfl
|
|
dc.w EXT_RZ-tblovfl
|
|
dc.w EXT_RM-tblovfl
|
|
dc.w EXT_RP-tblovfl
|
|
dc.w SGL_RN-tblovfl
|
|
dc.w SGL_RZ-tblovfl
|
|
dc.w SGL_RM-tblovfl
|
|
dc.w SGL_RP-tblovfl
|
|
dc.w DBL_RN-tblovfl
|
|
dc.w DBL_RZ-tblovfl
|
|
dc.w DBL_RM-tblovfl
|
|
dc.w DBL_RP-tblovfl
|
|
dc.w error-tblovfl
|
|
dc.w error-tblovfl
|
|
dc.w error-tblovfl
|
|
dc.w error-tblovfl
|
|
|
|
*
|
|
* ovf_r_k --- overflow result calculation
|
|
*
|
|
* This entry point is used by kernel_ex.
|
|
*
|
|
* This forces the destination precision to be extended
|
|
*
|
|
* Input: operand in ETEMP
|
|
* Output: a result is in ETEMP (internal extended format)
|
|
*
|
|
|
|
ovf_r_k:
|
|
lea ETEMP(a6),a0 ;a0 points to source operand
|
|
bclr.b #sign_bit,ETEMP_EX(a6)
|
|
sne ETEMP_SGN(a6) ;convert to internal IEEE format
|
|
|
|
tst.b UFLG_TMP(a6) ; unsupported data format exception? <5/2/91, JPO> <T3>
|
|
beq.b @1 ; no. get round precision from USER_FPCR <5/2/91, JPO> <T3>
|
|
|
|
btst.b #6,CMDREG1B+1(a6) ; yes. single/double instruction? <5/2/91, JPO> <T3>
|
|
beq.b @1 ; no. get precision from USER_FPCR <5/2/91, JPO> <T3>
|
|
|
|
moveq.l #1,d0 ; set precision to single <5/2/91, JPO> <T3>
|
|
btst.b #2,CMDREG1B+1(a6) ; double precision? <5/2/91, JPO> <T3>
|
|
beq.b ovf_res ; no. get result <5/2/91, JPO> <T3>
|
|
|
|
addq.l #1,d0 ; yes. set precision code in d0 <5/2/91, JPO> <T3>
|
|
bra.b ovf_res ; get result <5/2/91, JPO> <T3>
|
|
@1: ; <T3>
|
|
bfextu FPCR_MODE(a6){0:2},d0 ;set round precision
|
|
bra.b ovf_res
|
|
*
|
|
* ovf_r_x2 --- overflow result calculation
|
|
*
|
|
* This entry point used by x_ovfl. (opclass 0 and 2)
|
|
*
|
|
* Input a0 points to an operand in the internal extended format
|
|
* Output a0 points to the result in the internal extended format
|
|
*
|
|
* This sets the round precision according to the user's FPCR unless
|
|
* the instruction is fsgldiv or fsglmul, then the rounding precision
|
|
* must be set to extended.
|
|
*
|
|
|
|
ovf_r_x2:
|
|
btst.b #E3,E_BYTE(a6) ;check for nu exception
|
|
; beq.b ovf_fpcr ; DELETED <2/15/91, JPO>
|
|
beq.b ovf_cu ; check for special cu exception <2/15/91, JPO>
|
|
;ovf_e3_exc: ; label DELETED <2/15/91, JPO>
|
|
move.w CMDREG3B(a6),d0
|
|
andi.w #$7f,d0
|
|
|
|
; Check for special precision-constraining operations (FSXXX, FDXXX,
|
|
; FSGLDIV, and FSGLMUL) - ADDED <2/15/91, JPO>
|
|
|
|
btst.l #6,d0 ; FSXXX or FDXXX instruction? <2/15/91, JPO>
|
|
beq.b ovf_e3_fsgl ; no. check for FSGLXXX <2/15/91, JPO>
|
|
btst.l #5,d0 ; yes. which one? <2/15/91, JPO>
|
|
beq.b ovf_sgl ; single-precision <2/15/91, JPO>
|
|
moveq.l #2,d0 ; double precision <2/15/91, JPO>
|
|
bra.b ovf_res
|
|
|
|
ovf_sgl: ; single-precision rounding <2/15/91, JPO>
|
|
moveq.l #1,d0
|
|
bra.b ovf_res
|
|
|
|
ovf_e3_fsgl: ; label ADDED <2/15/91, JPO>
|
|
cmpi.w #$30,d0
|
|
beq.b ovf_fsgl
|
|
cmpi.w #$33,d0
|
|
bne.b ovf_fpcr
|
|
*
|
|
* Inst is either fsgldiv or fsglmul. Force extended precision.
|
|
*
|
|
ovf_fsgl:
|
|
clr.l d0
|
|
bra.b ovf_res
|
|
;
|
|
; E1 opclass 0 or 2 exception. Check for special precision-constraining
|
|
; operations (FSXXX/FDXXX)
|
|
;
|
|
ovf_cu: ; <2/15/91, JPO>
|
|
move.w CMDREG1B(a6),d0 ; isolate key opmode bits in D0 <2/15/91, JPO>
|
|
and.l #$44,d0 ; <2/15/91, JPO>
|
|
btst.l #6,d0 ; FSXXX or FDXXX instruction? <2/15/91, JPO>
|
|
beq.b ovf_fpcr ; no, precision in FPCR <2/15/91, JPO>
|
|
addq.l #1,d0 ; yes <2/15/91, JPO>
|
|
btst.l #2,d0 ; which one? <2/15/91, JPO>
|
|
beq.b @1 ; single <2/15/91, JPO>
|
|
addq.l #1,d0 ; double <2/15/91, JPO>
|
|
@1:
|
|
and.b #3,d0 ; isolate precision bits <2/15/91, JPO>
|
|
bra.b ovf_res ; <2/15/91, JPO>
|
|
|
|
*
|
|
* Inst is not either fsgldiv or fsglmul. The precision is in the fpcr.
|
|
*
|
|
ovf_fpcr:
|
|
bfextu FPCR_MODE(a6){0:2},d0 ;set round precision
|
|
bra.b ovf_res
|
|
|
|
*
|
|
*
|
|
* ovf_r_x3 --- overflow result calculation
|
|
*
|
|
* This entry point used by x_ovfl. (opclass 3 only)
|
|
*
|
|
* Input a0 points to an operand in the internal extended format
|
|
* Output a0 points to the result in the internal extended format
|
|
*
|
|
* This sets the round precision according to the destination size.
|
|
*
|
|
|
|
ovf_r_x3:
|
|
bsr g_dfmtou ;get dest fmt in d0{1:0}
|
|
* ;for fmovout, the destination format
|
|
* ;is the rounding precision
|
|
|
|
*
|
|
* ovf_res --- overflow result calculation
|
|
*
|
|
* Input:
|
|
* a0 points to operand in internal extended format
|
|
* Output:
|
|
* a0 points to result in internal extended format
|
|
*
|
|
|
|
ovf_res:
|
|
lsl.l #2,d0 ;move round precision to d0{3:2}
|
|
bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
|
|
or.l d1,d0 ;index is fmt:mode in d0{3:0}
|
|
lea.l tblovfl,a1 ;load a1 with table address
|
|
; move.l (a1,d0*4),a1 ;use d0 as index to the table - deleted <1/8/91, JPO>
|
|
adda.w (a1,d0.w*2),a1 ; <1/8/91, JPO>
|
|
jmp (a1) ;go to the correct routine
|
|
*
|
|
*case DEST_FMT = EXT
|
|
*
|
|
EXT_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra set_sign ;now go set the sign
|
|
EXT_RZ:
|
|
lea.l EXT_PLRG,a1 ;answer is +/- large number
|
|
bra set_sign ;now go set the sign
|
|
EXT_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b e_rm_pos
|
|
e_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra end_ovfr
|
|
e_rm_pos:
|
|
lea.l EXT_PLRG,a1 ;answer is large positive number
|
|
bra end_ovfr
|
|
EXT_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b e_rp_pos
|
|
e_rp_neg:
|
|
lea.l EXT_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
e_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is positive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
*
|
|
*case DEST_FMT = DBL
|
|
*
|
|
DBL_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra set_sign
|
|
DBL_RZ:
|
|
lea.l DBL_PLRG,a1 ;answer is +/- large number
|
|
bra set_sign ;now go set the sign
|
|
DBL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b d_rm_pos
|
|
d_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra.b end_ovfr ;inf is same for all precisions (ext,dbl,sgl)
|
|
d_rm_pos:
|
|
lea.l DBL_PLRG,a1 ;answer is large positive number
|
|
bra.b end_ovfr
|
|
DBL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b d_rp_pos
|
|
d_rp_neg:
|
|
lea.l DBL_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
d_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is positive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
*
|
|
*case DEST_FMT = SGL
|
|
*
|
|
SGL_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra.b set_sign
|
|
SGL_RZ:
|
|
lea.l SGL_PLRG,a1 ;anwer is +/- large number
|
|
bra.b set_sign
|
|
SGL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b s_rm_pos
|
|
s_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra.b end_ovfr
|
|
s_rm_pos:
|
|
lea.l SGL_PLRG,a1 ;answer is large positive number
|
|
bra.b end_ovfr
|
|
SGL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b s_rp_pos
|
|
s_rp_neg:
|
|
lea.l SGL_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
s_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is positive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
|
|
set_sign:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b end_ovfr
|
|
neg_sign:
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
|
|
end_ovfr:
|
|
move.w LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign
|
|
move.l LOCAL_HI(a1),LOCAL_HI(a0)
|
|
move.l LOCAL_LO(a1),LOCAL_LO(a0)
|
|
rts
|
|
|
|
|
|
*
|
|
* ERROR
|
|
*
|
|
error:
|
|
rts
|
|
*
|
|
* get_fline --- get f-line opcode of interrupted instruction --- DELETED <1/8/91, JPO>
|
|
*
|
|
* Returns opcode in the low word of d0.
|
|
*
|
|
;get_fline: ; subroutine DELETED <1/8/91, JPO>
|
|
; move.l USER_FPIAR(a6),a0 ;opcode address
|
|
; move.l #0,-(a7) ;reserve a word on the stack
|
|
; lea.l 2(a7),a1 ;point to low word of temporary
|
|
; move.l #2,d0 ;count
|
|
; bsr mem_read
|
|
; move.l (a7)+,d0
|
|
; rts
|
|
*
|
|
* g_rndpr --- put rounding precision in d0{1:0}
|
|
*
|
|
* valid return codes are:
|
|
* 00 - extended
|
|
* 01 - single
|
|
* 10 - double
|
|
*
|
|
* begin
|
|
* get rounding precision (cmdreg3b{6:5})
|
|
* begin
|
|
* case opclass = 011 (move out)
|
|
* get destination format - this is the also the rounding precision
|
|
*
|
|
* case opclass = 0x0
|
|
* if E3
|
|
* *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL
|
|
* *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL
|
|
* case RndPr(from cmdreg3b{6:5} = 00 | 01
|
|
* use precision from FPCR{7:6}
|
|
* case 00 then RND_PREC = EXT
|
|
* case 01 then RND_PREC = SGL
|
|
* case 10 then RND_PREC = DBL
|
|
* else E1
|
|
* use precision in FPCR{7:6}
|
|
* case 00 then RND_PREC = EXT
|
|
* case 01 then RND_PREC = SGL
|
|
* case 10 then RND_PREC = DBL
|
|
* end
|
|
*
|
|
g_rndpr:
|
|
bsr.b g_opcls ;get opclass in d0{2:0}
|
|
cmp.w #$0003,d0 ;check for opclass 011
|
|
bne.b op_0x0
|
|
|
|
*
|
|
* For move out instructions (opclass 011) the destination format
|
|
* is the same as the rounding precision. Pass results from g_dfmtou.
|
|
*
|
|
bsr.b g_dfmtou
|
|
rts
|
|
op_0x0:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b rnd_e1
|
|
|
|
move.l CMDREG3B(a6),d0 ;rounding precision in d0{10:9}
|
|
bfextu d0{9:2},d0 ;move the rounding prec bits to d0{1:0}
|
|
; btst.l #30,d0 ;check either of the ext codes - WRONG bit <2/15/91, JPO>
|
|
btst.l #1,d0 ; FSXXX or FDXXX? <2/15/91, JPO>
|
|
; beq.b rnd_e1 ;if cmd3b has size=ext, check FPCR bits - DELETED <2/15/91, JPO>
|
|
beq.b g_fpcrmode ; new label <2/15/91, JPO>
|
|
*
|
|
* Convert to return format. The values from cmdreg3b and the return
|
|
* values are:
|
|
* cmdreg3b return precision
|
|
* -------- ------ ---------
|
|
* 00,01 0 ext
|
|
* 10 1 sgl
|
|
* 11 2 dbl
|
|
*
|
|
cmpi.l #2,d0
|
|
; blt.b rnd_ext ; DELETED---not possible <2/15/91, JPO>
|
|
beq.b rnd_sgl
|
|
rnd_dbl:
|
|
move.l #2,d0
|
|
rts
|
|
;rnd_ext: ; DELETED---not possible <2/15/91, JPO>
|
|
; clr.l d0
|
|
; rts
|
|
rnd_sgl:
|
|
move.l #1,d0
|
|
rts
|
|
*
|
|
* Get rounding precision set in FPCR{7:6} if E1 exception not due to new
|
|
* precision-constraining instructions of form FSXXX or FDXXX. <2/15/91, JPO>
|
|
*
|
|
rnd_e1:
|
|
move.w CMDREG1B(a6),d0 ; isolate key opmode bits in D0 <2/15/91, JPO>
|
|
and.l #$44,d0 ; <2/15/91, JPO>
|
|
btst.l #6,d0 ; FSXXX or FDXXX instruction? <2/15/91, JPO>
|
|
beq.b g_fpcrmode ; no, precision in FPCR <2/15/91, JPO>
|
|
addq.l #1,d0 ; yes <2/15/91, JPO>
|
|
btst.l #2,d0 ; which one? <2/15/91, JPO>
|
|
beq.b @1 ; single <2/15/91, JPO>
|
|
addq.l #1,d0 ; double <2/15/91, JPO>
|
|
@1:
|
|
and.b #3,d0 ; isolate precision bits <2/15/91, JPO>
|
|
rts ; <2/15/91, JPO>
|
|
|
|
g_fpcrmode: ; NEW label <2/15/91, JPO>
|
|
move.l USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6}
|
|
bfextu d0{24:2},d0 ;move the rounding prec bits to d0{1:0}
|
|
rts
|
|
*
|
|
* g_opcls --- put opclass in d0{2:0}
|
|
*
|
|
g_opcls:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b opc_1b ;if set, go to cmdreg1b
|
|
opc_3b:
|
|
clr.l d0 ;if E3, only opclass 0x0 is possible
|
|
rts
|
|
opc_1b:
|
|
move.l CMDREG1B(a6),d0
|
|
bfextu d0{0:3},d0 ;shift opclass bits d0{31:29} to d0{2:0}
|
|
rts
|
|
*
|
|
* g_dfmtou --- put destination format in d0{1:0}
|
|
*
|
|
* If E1, the format is from cmdreg1b{12:10}
|
|
* If E3, the format is extended.
|
|
*
|
|
* Dest. Fmt.
|
|
* extended 010 -> 00
|
|
* single 001 -> 01
|
|
* double 101 -> 10
|
|
*
|
|
g_dfmtou:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b op011
|
|
clr.l d0 ;if E1, size is always ext
|
|
rts
|
|
op011:
|
|
move.l CMDREG1B(a6),d0
|
|
bfextu d0{3:3},d0 ;dest fmt from cmdreg1b{12:10}
|
|
cmp.b #1,d0 ;check for single
|
|
bne.b not_sgl
|
|
move.l #1,d0
|
|
rts
|
|
not_sgl:
|
|
cmp.b #5,d0 ;check for double
|
|
bne.b not_dbl
|
|
move.l #2,d0
|
|
rts
|
|
not_dbl:
|
|
clr.l d0 ;must be extended
|
|
rts
|
|
|
|
*
|
|
*
|
|
* Final result table for unf_sub. Note that the negative counterparts
|
|
* are unnecessary as unf_sub always returns the sign separately from
|
|
* the exponent.
|
|
* ;+zero
|
|
ALIGN 16
|
|
EXT_PZRO dc.l $00000000,$00000000,$00000000,$00000000
|
|
* ;+zero
|
|
SGL_PZRO dc.l $3f810000,$00000000,$00000000,$00000000
|
|
* ;+zero
|
|
DBL_PZRO dc.l $3c010000,$00000000,$00000000,$00000000
|
|
* ;smallest +ext denorm
|
|
EXT_PSML dc.l $00000000,$00000000,$00000001,$00000000
|
|
* ;smallest +sgl denorm
|
|
SGL_PSML dc.l $3f810000,$00000100,$00000000,$00000000
|
|
* ;smallest +dbl denorm
|
|
DBL_PSML dc.l $3c010000,$00000000,$00000800,$00000000
|
|
*
|
|
* UNF_SUB --- underflow result calculation
|
|
*
|
|
* Input:
|
|
* d0 contains round precision
|
|
* a0 points to input operand in the internal extended format
|
|
*
|
|
* Output:
|
|
* a0 points to correct internal extended precision result.
|
|
*
|
|
|
|
tblunf: ; table MODIFIED <1/8/91, JPO>
|
|
dc.w uEXT_RN-tblunf
|
|
dc.w uEXT_RZ-tblunf
|
|
dc.w uEXT_RM-tblunf
|
|
dc.w uEXT_RP-tblunf
|
|
dc.w uSGL_RN-tblunf
|
|
dc.w uSGL_RZ-tblunf
|
|
dc.w uSGL_RM-tblunf
|
|
dc.w uSGL_RP-tblunf
|
|
dc.w uDBL_RN-tblunf
|
|
dc.w uDBL_RZ-tblunf
|
|
dc.w uDBL_RM-tblunf
|
|
dc.w uDBL_RP-tblunf
|
|
dc.w uDBL_RN-tblunf
|
|
dc.w uDBL_RZ-tblunf
|
|
dc.w uDBL_RM-tblunf
|
|
dc.w uDBL_RP-tblunf
|
|
|
|
|
|
unf_sub:
|
|
lsl.l #2,d0 ;move round precision to d0{3:2}
|
|
bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
|
|
or.l d1,d0 ;index is fmt:mode in d0{3:0}
|
|
lea.l tblunf,a1 ;load a1 with table address
|
|
; move.l (a1,d0*4),a1 ;use d0 as index to the table - deleted <1/8/91, JPO>
|
|
adda.w (a1,d0.w*2),a1 ; <1/8/91, JPO>
|
|
jmp (a1) ;go to the correct routine
|
|
*
|
|
*case DEST_FMT = EXT
|
|
*
|
|
uEXT_RN:
|
|
lea.l EXT_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uEXT_RZ:
|
|
lea.l EXT_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uEXT_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative underflow
|
|
beq.b ue_rm_pos
|
|
ue_rm_neg:
|
|
lea.l EXT_PSML,a1 ;answer is negative smallest denorm
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
ue_rm_pos:
|
|
lea.l EXT_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
uEXT_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative underflow
|
|
beq.b ue_rp_pos
|
|
ue_rp_neg:
|
|
lea.l EXT_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra end_unfr
|
|
ue_rp_pos:
|
|
lea.l EXT_PSML,a1 ;answer is positive smallest denorm
|
|
bra end_unfr
|
|
*
|
|
*case DEST_FMT = DBL
|
|
*
|
|
uDBL_RN:
|
|
lea.l DBL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign
|
|
uDBL_RZ:
|
|
lea.l DBL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uDBL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b ud_rm_pos
|
|
ud_rm_neg:
|
|
lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
ud_rm_pos:
|
|
lea.l DBL_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b end_unfr
|
|
uDBL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b ud_rp_pos
|
|
ud_rp_neg:
|
|
lea.l DBL_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra.b end_unfr
|
|
ud_rp_pos:
|
|
lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
|
|
bra.b end_unfr
|
|
*
|
|
*case DEST_FMT = SGL
|
|
*
|
|
uSGL_RN:
|
|
lea.l SGL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b uset_sign
|
|
uSGL_RZ:
|
|
lea.l SGL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b uset_sign
|
|
uSGL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b us_rm_pos
|
|
us_rm_neg:
|
|
lea.l SGL_PSML,a1 ;answer is smallest denormalized negative
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra.b end_unfr
|
|
us_rm_pos:
|
|
lea.l SGL_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b end_unfr
|
|
uSGL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b us_rp_pos
|
|
us_rp_neg:
|
|
lea.l SGL_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra.b end_unfr
|
|
us_rp_pos:
|
|
lea.l SGL_PSML,a1 ;answer is smallest denormalized positive
|
|
bra.b end_unfr
|
|
|
|
uset_sign:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b end_unfr
|
|
uneg_sign:
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
|
|
end_unfr:
|
|
move.w LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign
|
|
move.l LOCAL_HI(a1),LOCAL_HI(a0)
|
|
move.l LOCAL_LO(a1),LOCAL_LO(a0)
|
|
rts
|
|
*
|
|
* reg_dest --- write byte, word, or long data to Dn
|
|
*
|
|
*
|
|
* Input:
|
|
* L_SCR1: Data
|
|
* d1: data size and dest register number formatted as:
|
|
*
|
|
* 32 5 4 3 2 1 0
|
|
* -----------------------------------------------
|
|
* | 0 | Size | Dest Reg # |
|
|
* -----------------------------------------------
|
|
*
|
|
* Size is:
|
|
* 0 - Byte
|
|
* 1 - Word
|
|
* 2 - Long/Single
|
|
*
|
|
pregdst: ; table MODIFIED <1/8/91, JPO>
|
|
dc.w byte_d0-pregdst
|
|
dc.w byte_d1-pregdst
|
|
dc.w byte_d2-pregdst
|
|
dc.w byte_d3-pregdst
|
|
dc.w byte_d4-pregdst
|
|
dc.w byte_d5-pregdst
|
|
dc.w byte_d6-pregdst
|
|
dc.w byte_d7-pregdst
|
|
dc.w word_d0-pregdst
|
|
dc.w word_d1-pregdst
|
|
dc.w word_d2-pregdst
|
|
dc.w word_d3-pregdst
|
|
dc.w word_d4-pregdst
|
|
dc.w word_d5-pregdst
|
|
dc.w word_d6-pregdst
|
|
dc.w word_d7-pregdst
|
|
dc.w long_d0-pregdst
|
|
dc.w long_d1-pregdst
|
|
dc.w long_d2-pregdst
|
|
dc.w long_d3-pregdst
|
|
dc.w long_d4-pregdst
|
|
dc.w long_d5-pregdst
|
|
dc.w long_d6-pregdst
|
|
dc.w long_d7-pregdst
|
|
|
|
reg_dest:
|
|
lea.l pregdst,a0
|
|
; move.l (a0,d1*4),a0 ; deleted <1/8/91, JPO>
|
|
adda.w (a0,d1.w*2),a0 ; <1/8/91, JPO>
|
|
jmp (a0)
|
|
|
|
byte_d0:
|
|
move.b L_SCR1(a6),USER_D0+3(a6)
|
|
rts
|
|
byte_d1:
|
|
move.b L_SCR1(a6),USER_D1+3(a6)
|
|
rts
|
|
byte_d2:
|
|
move.b L_SCR1(a6),d2
|
|
rts
|
|
byte_d3:
|
|
move.b L_SCR1(a6),d3
|
|
rts
|
|
byte_d4:
|
|
move.b L_SCR1(a6),d4
|
|
rts
|
|
byte_d5:
|
|
move.b L_SCR1(a6),d5
|
|
rts
|
|
byte_d6:
|
|
move.b L_SCR1(a6),d6
|
|
rts
|
|
byte_d7:
|
|
move.b L_SCR1(a6),d7
|
|
rts
|
|
word_d0:
|
|
move.w L_SCR1(a6),USER_D0+2(a6)
|
|
rts
|
|
word_d1:
|
|
move.w L_SCR1(a6),USER_D1+2(a6)
|
|
rts
|
|
word_d2:
|
|
move.w L_SCR1(a6),d2
|
|
rts
|
|
word_d3:
|
|
move.w L_SCR1(a6),d3
|
|
rts
|
|
word_d4:
|
|
move.w L_SCR1(a6),d4
|
|
rts
|
|
word_d5:
|
|
move.w L_SCR1(a6),d5
|
|
rts
|
|
word_d6:
|
|
move.w L_SCR1(a6),d6
|
|
rts
|
|
word_d7:
|
|
move.w L_SCR1(a6),d7
|
|
rts
|
|
long_d0:
|
|
move.l L_SCR1(a6),USER_D0(a6)
|
|
rts
|
|
long_d1:
|
|
move.l L_SCR1(a6),USER_D1(a6)
|
|
rts
|
|
long_d2:
|
|
move.l L_SCR1(a6),d2
|
|
rts
|
|
long_d3:
|
|
move.l L_SCR1(a6),d3
|
|
rts
|
|
long_d4:
|
|
move.l L_SCR1(a6),d4
|
|
rts
|
|
long_d5:
|
|
move.l L_SCR1(a6),d5
|
|
rts
|
|
long_d6:
|
|
move.l L_SCR1(a6),d6
|
|
rts
|
|
long_d7:
|
|
move.l L_SCR1(a6),d7
|
|
rts
|
|
|
|
|