mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 16:49:18 +00:00
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
|
|
|
|
|