mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-25 09:30:50 +00:00
508 lines
15 KiB
Plaintext
508 lines
15 KiB
Plaintext
|
;
|
||
|
; File: Scale.a
|
||
|
;
|
||
|
; Contains: Emulation of the FSCALE unimplemented instruction
|
||
|
;
|
||
|
; 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):
|
||
|
;
|
||
|
; <1+> 6/24/91 BG Modified "src_small" not to set STORE_FLG (in case
|
||
|
; rounding precision is narrower than extended) and not
|
||
|
; to set UNFL bit in USER_FPSR (since t_resdnrm will do it).
|
||
|
; <1> 3/30/91 BG First checked into TERROR/BBS.
|
||
|
;
|
||
|
|
||
|
; scale.a
|
||
|
|
||
|
; Based upon Motorola file 'scale.sa'.
|
||
|
|
||
|
; CHANGE LOG:
|
||
|
; 07 Jan 91 JPO Deleted unreferenced labels "src_small", "den_done",
|
||
|
; "src_pos", "zer_rp", "zer_rp2", "neg_zero", and
|
||
|
; "res_pos". Renamed labels "ovfl", "denorm",
|
||
|
; "not_zero", and "pos_zero" to "sc_ovfl", "sc_denorm",
|
||
|
; "sc_notzero", and "sc_poszero", respectively, to avoid
|
||
|
; duplicate symbols.
|
||
|
; 07 Feb 91 JPO Modified "fix_dnrm" routine to keep track of guard/round
|
||
|
; bits in order to correctly round the result. For
|
||
|
; inexact underflows, set unfl/aunfl/inex2/inex bits
|
||
|
; in USER_FPSR(a6). Modified order of tests in "dst_loop"
|
||
|
; in order to avoid spurious underflow signaling for
|
||
|
; normal FSCALE results with zero exponent resulting
|
||
|
; from nonnegative scale factors.
|
||
|
; 08 Feb 91 JPO Prior to calling "t_resdnrm", put subnormal results in
|
||
|
; FPTEMP(a6) and set a0 to point to FPTEMP(a6). This
|
||
|
; avoids clobbering of ETEMP with result value.
|
||
|
;
|
||
|
|
||
|
*
|
||
|
* scale.sa 3.1 12/10/90
|
||
|
*
|
||
|
* The entry point sSCALE computes the destination operand
|
||
|
* scaled by the source operand. If the absolute value of
|
||
|
* the source operand is (>= 2^14) an overflow or underflow
|
||
|
* is returned.
|
||
|
*
|
||
|
* The entry point sscale is called from do_func to emulate
|
||
|
* the fscale unimplemented instruction.
|
||
|
*
|
||
|
* Input: Double-extended destination operand in FPTEMP,
|
||
|
* double-extended source operand in ETEMP.
|
||
|
*
|
||
|
* Output: The function returns scale(X,Y) to fp0.
|
||
|
*
|
||
|
* Modifies: fp0.
|
||
|
*
|
||
|
* Algorithm:
|
||
|
*
|
||
|
* 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.
|
||
|
|
||
|
* SCALE IDNT 2,1 Motorola 040 Floating Point Software Package
|
||
|
|
||
|
|
||
|
|
||
|
SRC_BNDS dc.w $3fff,$400c
|
||
|
|
||
|
*
|
||
|
* This entry point is used by the unimplemented instruction exception
|
||
|
* handler.
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
* FSCALE
|
||
|
*
|
||
|
|
||
|
sscale:
|
||
|
fmove.l #0,fpcr ;clr user enabled exc
|
||
|
clr.l d1
|
||
|
move.w FPTEMP(a6),d1 ;get dest exponent
|
||
|
smi L_SCR1(a6) ;use L_SCR1 to hold sign
|
||
|
andi.l #$7fff,d1 ;strip sign
|
||
|
move.w ETEMP(a6),d0 ;check src bounds
|
||
|
andi.w #$7fff,d0 ;clr sign bit
|
||
|
cmp2.w SRC_BNDS,d0
|
||
|
bcc.b src_in
|
||
|
cmpi.w #$400c,d0 ;test for too large
|
||
|
bge.w src_out
|
||
|
*
|
||
|
* The source input is below 1, so we check for denormalized numbers
|
||
|
* and set unfl.
|
||
|
*
|
||
|
;src_small: ; label not referenced <1/7/91, JPO>
|
||
|
move.b DTAG(a6),d0
|
||
|
andi.b #$e0,d0
|
||
|
tst.b d0
|
||
|
beq.b no_denorm
|
||
|
; st STORE_FLG(a6) ;dest already contains result - DELETED <6/13/91, JPO> <T2>
|
||
|
; or.l #unfl_mask,USER_FPSR(a6) ;set UNFL - DELETED <6/13/91, JPO> <T2>
|
||
|
;den_done: ; label not referenced <1/7/91, JPO>
|
||
|
lea.l FPTEMP(a6),a0
|
||
|
bra t_resdnrm
|
||
|
no_denorm:
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0 ;simply return dest
|
||
|
rts
|
||
|
|
||
|
|
||
|
*
|
||
|
* Source is within 2^14 range. To perform the int operation,
|
||
|
* move it to d0.
|
||
|
*
|
||
|
src_in:
|
||
|
fmove.x ETEMP(a6),fp0 ;move in src for int
|
||
|
fmove.l #rz_mode,fpcr ;force rz for src conversion
|
||
|
fmove.l fp0,d0 ;int src to d0
|
||
|
fmove.l #0,FPSR ;clr status from above
|
||
|
tst.w ETEMP(a6) ;check src sign
|
||
|
blt.w src_neg
|
||
|
*
|
||
|
* Source is positive. Add the src to the dest exponent.
|
||
|
* The result can be denormalized, if src = 0, or overflow,
|
||
|
* if the result of the add sets a bit in the upper word.
|
||
|
*
|
||
|
;src_pos: ; label not referenced <1/7/91, JPO>
|
||
|
tst.w d1 ;check for denorm
|
||
|
beq.w dst_dnrm
|
||
|
add.l d0,d1 ;add src to dest exp
|
||
|
beq.b sc_denorm ;if zero, result is denorm - label renamed <1/7/91, JPO>
|
||
|
cmpi.l #$7fff,d1 ;test for overflow
|
||
|
bge.b sc_ovfl ; label renamed <1/7/91, JPO>
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b spos_pos
|
||
|
or.w #$8000,d1
|
||
|
spos_pos:
|
||
|
move.w d1,FPTEMP(a6) ;result in FPTEMP
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0 ;write result to fp0
|
||
|
rts
|
||
|
sc_ovfl: ; label renamed <1/7/91, JPO>
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b sovl_pos
|
||
|
or.w #$8000,d1
|
||
|
sovl_pos:
|
||
|
move.w FPTEMP(a6),ETEMP(a6) ;result in ETEMP
|
||
|
move.l FPTEMP_HI(a6),ETEMP_HI(a6)
|
||
|
move.l FPTEMP_LO(a6),ETEMP_LO(a6)
|
||
|
bra t_ovfl2
|
||
|
|
||
|
sc_denorm: ; label renamed <1/7/91, JPO>
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b den_pos
|
||
|
or.w #$8000,d1
|
||
|
den_pos:
|
||
|
tst.l FPTEMP_HI(a6) ;check j bit
|
||
|
blt.b nden_exit ;if set, not denorm
|
||
|
;;; move.w d1,ETEMP(a6) ;input expected in ETEMP - DELETED <2/8/91, JPO>
|
||
|
move.w d1,FPTEMP(a6) ; input can be in FPTEMP <2/8/91, JPO>
|
||
|
;;; move.l FPTEMP_HI(a6),ETEMP_HI(a6) ; DELETED <2/8/91, JPO>
|
||
|
;;; move.l FPTEMP_LO(a6),ETEMP_LO(a6) ; DELETED <2/8/91, JPO>
|
||
|
; or.l #unfl_bit,USER_FPSR(a6) ;set unfl - DELETED <2/7/91, JPO>
|
||
|
or.l #unfl_mask,USER_FPSR(a6) ; set unfl <2/7/91, JPO>
|
||
|
;;; lea.l ETEMP(a6),a0 ; DELETED <2/8/91, JPO>
|
||
|
lea.l FPTEMP(a6),a0 ; <2/8/91, JPO>
|
||
|
bra t_resdnrm
|
||
|
nden_exit:
|
||
|
move.w d1,FPTEMP(a6) ;result in FPTEMP
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0 ;write result to fp0
|
||
|
rts
|
||
|
|
||
|
*
|
||
|
* Source is negative. Add the src to the dest exponent.
|
||
|
* (The result exponent will be reduced). The result can be
|
||
|
* denormalized.
|
||
|
*
|
||
|
src_neg:
|
||
|
add.l d0,d1 ;add src to dest
|
||
|
beq.b sc_denorm ;if zero, result is denorm - label renamed <1/7/91, JPO>
|
||
|
blt.b fix_dnrm ;if negative, result is
|
||
|
* ;needing denormalization
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b sneg_pos
|
||
|
or.w #$8000,d1
|
||
|
sneg_pos:
|
||
|
move.w d1,FPTEMP(a6) ;result in FPTEMP
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0 ;write result to fp0
|
||
|
rts
|
||
|
|
||
|
|
||
|
*
|
||
|
* The result exponent is below denorm value. Test for catastrophic
|
||
|
* underflow and force zero if true. If not, try to shift the
|
||
|
* mantissa right until a zero exponent exists.
|
||
|
*
|
||
|
fix_dnrm:
|
||
|
; cmpi.w #$ffc0,d1 ;lower bound for normalization - DELETED <2/7/91>
|
||
|
; blt.w fix_unfl ;if lower, catastrophic unfl - DELETED <2/7/91>
|
||
|
move.w d1,d0 ;use d0 for exp
|
||
|
; move.l d2,-(a7) ;free d2 for norm - DELETED <2/7/91>
|
||
|
movem.l d2-d3,-(a7) ; free d2/d3 for norm <2/7/91>
|
||
|
move.l FPTEMP_HI(a6),d1
|
||
|
move.l FPTEMP_LO(a6),d2
|
||
|
; clr.l L_SCR2(a6) ; DELETED <2/7/91>
|
||
|
clr.l d3 ; initialize stickies <2/7/91>
|
||
|
cmpi.w #$ffe0,d0 ; shift count >= 32 bits? <2/7/91>
|
||
|
bgt.b fix_loop ; no, do shift <2/7/91>
|
||
|
|
||
|
move.l d2,d3 ; yes, shift 32 bits <2/7/91>
|
||
|
move.l d1,d2 ; <2/7/91>
|
||
|
clr.l d1 ; high significand is zero <2/7/91>
|
||
|
add.w #32,d0 ; adjust shift counter <2/7/91>
|
||
|
beq.b done_fix ; don't shift if zero <2/7/91>
|
||
|
|
||
|
cmpi.w #$ffe0,d0 ; new shift count > 32 bits? <2/7/91>
|
||
|
bge.b fix_loop ; no, do shift <2/7/91>
|
||
|
|
||
|
clr.l d2 ; yes, result is 0 with a sticky <2/7/91>
|
||
|
moveq.l #1,d3 ; <2/7/91>
|
||
|
bra.b done_fix ; <2/7/91>
|
||
|
|
||
|
fix_loop:
|
||
|
; add.w #1,d0 ;drive d0 to 0 - DELETED <2/7/91>
|
||
|
lsr.l #1,d1 ;while shifting the
|
||
|
roxr.l #1,d2 ;mantissa to the right
|
||
|
roxr.l #1,d3 ; into the guard/stickies (d3)
|
||
|
bcc.b no_carry
|
||
|
; st L_SCR2(a6) ;use L_SCR2 to capture inex - DELETED <2/7/91>
|
||
|
ori.b #1,d3 ; don't lose low sticky <2/7/91>
|
||
|
no_carry:
|
||
|
; tst.w d0 ;it is finished when - DELETED <2/7/91>
|
||
|
; blt.b fix_loop ;d0 is zero or the mantissa - DELETED <2/7/91>
|
||
|
add.w #1,d0 ; drive loop count in d0 to 0 <2/7/91>
|
||
|
bne.b fix_loop ; <2/7/91>
|
||
|
|
||
|
done_fix: ; label added <2/7/91>
|
||
|
; tst.b L_SCR2(a6) ; DELETED <2/7/91>
|
||
|
; beq.b tst_zero ; DELETED <2/7/91>
|
||
|
; or.l #unfl_inx_mask,USER_FPSR(a6) ; DELETED <2/7/91>
|
||
|
* ;set aunfl, aunfl, ainex
|
||
|
*
|
||
|
* Test for zero. If zero, simply use fmove to return +/- zero
|
||
|
* to the fpu.
|
||
|
*
|
||
|
;tst_zero: ; label DELETED <2/7/91>
|
||
|
clr.w FPTEMP_EX(a6)
|
||
|
tst.b L_SCR1(a6) ;test for sign
|
||
|
; beq.b tst_con ; DELETED <2/7/91>
|
||
|
beq.b sc_round ; new label <2/7/91>
|
||
|
or.w #$8000,FPTEMP_EX(a6) ;set sign bit
|
||
|
|
||
|
;
|
||
|
; Round result to extended precision, honoring rounding direction
|
||
|
; in USER_FPCR(a6) and setting appropriate exceptions - <2/7/91>
|
||
|
;
|
||
|
sc_round: ; new label <2/7/91>
|
||
|
or.l #unfl_mask,USER_FPSR(a6) ; set unfl at very least <2/7/91>
|
||
|
tst.l d3 ; check for inexact <2/7/91>
|
||
|
beq.b sc_rddone ; exact, no rounding necessary <2/7/91>
|
||
|
;
|
||
|
; Inexact result may require rounding tweak
|
||
|
;
|
||
|
or.l #unfinx_mask,USER_FPSR(a6) ; set unfl/aunfl/inex2/ainex, also <2/7/91>
|
||
|
bfextu FPCR_MODE(a6){2:2},d0 ; rounding direction in d0.low <2/7/91>
|
||
|
beq.b sc_rn ; to nearest mode <2/7/91>
|
||
|
btst.l #1,d0 ; check for round toward ±inf <2/7/91>
|
||
|
beq.b sc_rddone ; toward zero rounding -> done <2/7/91>
|
||
|
|
||
|
btst.l #0,d0 ; round toward +inf or -inf? <2/7/91>
|
||
|
bne.b sc_rp ; +inf <2/7/91>
|
||
|
;
|
||
|
; Rounding toward -inf. Increment significand if sign is negative <2/7/91>
|
||
|
;
|
||
|
tst.b L_SCR1(a6) ; check sign <2/7/91>
|
||
|
bne.b sc_rdinc ; negative -> incr signif <2/7/91>
|
||
|
bra.b sc_rddone ; positive -> done <2/7/91>
|
||
|
;
|
||
|
; Rounding toward +inf. Increment significand if sign is positive <2/7/91>
|
||
|
;
|
||
|
sc_rp: ; <2/7/91>
|
||
|
tst.b L_SCR1(a6) ; check sign <2/7/91>
|
||
|
beq.b sc_rdinc ; positive -> incr signif <2/7/91>
|
||
|
bra.b sc_rddone ; negative -> done <2/7/91>
|
||
|
;
|
||
|
; Round to nearest mode <2/7/91>
|
||
|
;
|
||
|
sc_rn: ; <2/7/91>
|
||
|
tst.l d3 ; test guard bit <2/7/91>
|
||
|
bpl.b sc_rddone ; clear -> done <2/7/91>
|
||
|
|
||
|
bftst d3{1:31} ; test stickies <2/7/91>
|
||
|
bne.b sc_rdinc ; set -> incr signif <2/7/91>
|
||
|
|
||
|
btst.l #0,d2 ; test lowest bit of signif <2/7/91>
|
||
|
beq.b sc_rddone ; clear -> done <2/7/91>
|
||
|
|
||
|
;
|
||
|
; Rounding requires increment of significand <2/7/91>
|
||
|
;
|
||
|
sc_rdinc: ; <2/7/91>
|
||
|
clr.l d0 ; clear d0 <2/7/91>
|
||
|
addq.l #1,d2 ; incr signif <2/7/91>
|
||
|
addx.l d0,d1 ; high result will not generate carry <2/7/91>
|
||
|
;
|
||
|
; Rounding done. Store significand result in FPTEMP and test
|
||
|
; for zero result.
|
||
|
;
|
||
|
;tst_con: ; label deleted <2/7/91>
|
||
|
sc_rddone: ; new label <2/7/91>
|
||
|
move.l d1,FPTEMP_HI(a6)
|
||
|
move.l d2,FPTEMP_LO(a6)
|
||
|
move.l d2,d0 ; save low signif in d0 <2/7/91>
|
||
|
; move.l (a7)+,d2 ; DELETED <2/7/91>
|
||
|
movem.l (a7)+,d2-d3 ; restore d2/d3
|
||
|
; tst.l d1 ; DELETED <2/7/91>
|
||
|
; bne.b sc_notzero ; label renamed <1/7/91, JPO> - DELETED <2/7/91>
|
||
|
; tst.l FPTEMP_LO(a6) ; DELETED <2/7/91>
|
||
|
|
||
|
or.l d1,d0 ; zero result? <2/7/91>
|
||
|
bne.b sc_notzero ; no - label RENAMED <1/7/91, JPO>
|
||
|
|
||
|
*
|
||
|
* Result is zero. Check for rounding mode to set lsb. If the
|
||
|
* mode is rp, and the zero is positive, return smallest denorm.
|
||
|
* If the mode is rm, and the zero is negative, return smallest
|
||
|
* negative denorm.
|
||
|
*
|
||
|
; btst.b #5,FPCR_MODE(a6) ;test if rm or rp - DELETED <1/7/91, JPO>
|
||
|
; beq.b no_dir ; DELETED <1/7/91, JPO>
|
||
|
; btst.b #4,FPCR_MODE(a6) ;check which one - DELETED <1/7/91, JPO>
|
||
|
; beq.b zer_rm ; DELETED <1/7/91, JPO>
|
||
|
;zer_rp: ; label not referenced <1/7/91, JPO> - DELETED <1/7/91, JPO>
|
||
|
; tst.b L_SCR1(a6) ;check sign - DELETED <1/7/91, JPO>
|
||
|
; bne.b no_dir ;if set, neg op, no inc - DELETED <1/7/91, JPO>
|
||
|
; move.l #1,FPTEMP_LO(a6) ;set lsb - DELETED <1/7/91, JPO>
|
||
|
; bra.b sm_dnrm ; DELETED <1/7/91, JPO>
|
||
|
;zer_rm: ; label DELETED <1/7/91, JPO>
|
||
|
; tst.b L_SCR1(a6) ;check sign - DELETED <1/7/91, JPO>
|
||
|
; beq.b no_dir ;if clr, neg op, no inc - DELETED <1/7/91, JPO>
|
||
|
; move.l #1,FPTEMP_LO(a6) ;set lsb - DELETED <1/7/91, JPO>
|
||
|
; or.l #neg_mask,USER_FPSR(a6) ;set N - DELETED <1/7/91, JPO>
|
||
|
; bra.b sm_dnrm ; DELETED <1/7/91, JPO>
|
||
|
;no_dir: ; label DELETED <1/7/91, JPO>
|
||
|
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0 ;use fmove to set cc's
|
||
|
rts
|
||
|
|
||
|
*
|
||
|
* The rounding mode changed the zero to a smallest denorm. Call
|
||
|
* t_resdnrm with exceptional operand in ETEMP.
|
||
|
*
|
||
|
;sm_dnrm: ; label DELETED <1/7/91, JPO>
|
||
|
; move.l FPTEMP_EX(a6),ETEMP_EX(a6) ; MOVED below "fix_exit" below <1/7/91, JPO>
|
||
|
; move.l FPTEMP_HI(a6),ETEMP_HI(a6) ; <1/7/91, JPO>
|
||
|
; move.l FPTEMP_LO(a6),ETEMP_LO(a6) ; <1/7/91, JPO>
|
||
|
; lea.l ETEMP(a6),a0 ; <1/7/91, JPO>
|
||
|
; bra t_resdnrm ; <1/7/91, JPO>
|
||
|
|
||
|
*
|
||
|
* Result is still denormalized.
|
||
|
*
|
||
|
sc_notzero: ;label renamed <1/7/91, JPO>
|
||
|
or.l #unfl_mask,USER_FPSR(a6) ;set unfl
|
||
|
tst.b L_SCR1(a6) ;check for sign
|
||
|
beq.b fix_exit
|
||
|
or.l #neg_mask,USER_FPSR(a6) ;set N
|
||
|
fix_exit:
|
||
|
; bra.b sm_dnrm ; DELETED <1/7/91, JPO>
|
||
|
|
||
|
;;; move.l FPTEMP_EX(a6),ETEMP_EX(a6) ; MOVED from above <1/7/91, JPO> - DELETED <2/8/91, JPO>
|
||
|
;;; move.l FPTEMP_HI(a6),ETEMP_HI(a6) ; <1/7/91, JPO> - DELETED <2/8/91, JPO>
|
||
|
;;; move.l FPTEMP_LO(a6),ETEMP_LO(a6) ; <1/7/91, JPO> - DELETED <2/8/91, JPO>
|
||
|
;;; lea.l ETEMP(a6),a0 ; <1/7/91, JPO> - DELETED <2/8/91, JPO>
|
||
|
lea.l FPTEMP(a6),a0 ; exceptional op in FPTEMP <2/8/91, JPO>
|
||
|
bra t_resdnrm ; <1/7/91, JPO>
|
||
|
|
||
|
|
||
|
*
|
||
|
* The result has underflowed to zero. Return zero and set
|
||
|
* unfl, aunfl, and ainex. DELETED <1/7/91, JPO>
|
||
|
*
|
||
|
;fix_unfl: ; DELETED routine <1/7/91, JPO>
|
||
|
; or.l #unfl_inx_mask,USER_FPSR(a6)
|
||
|
; btst.b #5,FPCR_MODE(a6) ;test if rm or rp
|
||
|
; beq.b no_dir2
|
||
|
; btst.b #4,FPCR_MODE(a6) ;check which one
|
||
|
; beq.b zer_rm2
|
||
|
;zer_rp2: ; label not referenced <1/7/91, JPO>
|
||
|
; tst.b L_SCR1(a6) ;check sign
|
||
|
; bne.b no_dir2 ;if set, neg op, no inc
|
||
|
; clr.l FPTEMP_EX(a6)
|
||
|
; clr.l FPTEMP_HI(a6)
|
||
|
; move.l #1,FPTEMP_LO(a6) ;set lsb
|
||
|
; bra.b sm_dnrm ;return smallest denorm
|
||
|
;zer_rm2:
|
||
|
; tst.b L_SCR1(a6) ;check sign
|
||
|
; beq.b no_dir2 ;if clr, neg op, no inc
|
||
|
; move.w #$8000,FPTEMP_EX(a6)
|
||
|
; clr.l FPTEMP_HI(a6)
|
||
|
; move.l #1,FPTEMP_LO(a6) ;set lsb
|
||
|
; or.l #neg_mask,USER_FPSR(a6) ;set N
|
||
|
; bra.w sm_dnrm ;return smallest denorm
|
||
|
;
|
||
|
;no_dir2:
|
||
|
; tst.b L_SCR1(a6)
|
||
|
; bge.b sc_poszero ; label renamed <1/7/91, JPO>
|
||
|
;neg_zero: ; label not referenced <1/7/91, JPO>
|
||
|
; fmove.s #"$80000000",fp0
|
||
|
; rts
|
||
|
;sc_poszero: ; label renamed <1/7/91, JPO>
|
||
|
; fmove.s #"$00000000",fp0
|
||
|
; rts
|
||
|
|
||
|
*
|
||
|
* The destination is a denormalized number. It must be handled
|
||
|
* by first shifting the bits in the mantissa until it is normalized,
|
||
|
* then adding the remainder of the source to the exponent.
|
||
|
*
|
||
|
dst_dnrm:
|
||
|
movem.l d2/d3,-(a7)
|
||
|
move.w FPTEMP_EX(a6),d1
|
||
|
move.l FPTEMP_HI(a6),d2
|
||
|
move.l FPTEMP_LO(a6),d3
|
||
|
dst_loop:
|
||
|
; tst.l d0 ;check if src is zero - test MOVED below following test <1/7/91, JPO>
|
||
|
; beq.b dst_fin ; <1/7/91, JPO>
|
||
|
tst.l d2 ;test for j-bit set
|
||
|
blt.b dst_norm
|
||
|
tst.l d0 ;check if src is zero - test MOVED from above <1/7/91, JPO>
|
||
|
beq.b dst_fin ; <1/7/91, JPO>
|
||
|
subi.l #1,d0 ;dec src
|
||
|
lsl.l #1,d3
|
||
|
roxl.l #1,d2
|
||
|
bra.b dst_loop
|
||
|
*
|
||
|
* Destination became normalized. Simply add the remaining
|
||
|
* portion of the src to the exponent.
|
||
|
*
|
||
|
dst_norm:
|
||
|
add.w d0,d1 ;dst is normalized; add src
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b dnrm_pos
|
||
|
or.l #$8000,d1
|
||
|
dnrm_pos:
|
||
|
movem.w d1,FPTEMP_EX(a6)
|
||
|
movem.l d2,FPTEMP_HI(a6)
|
||
|
movem.l d3,FPTEMP_LO(a6)
|
||
|
fmove.l USER_FPCR(a6),FPCR
|
||
|
fmove.x FPTEMP(a6),fp0
|
||
|
movem.l (a7)+,d2/d3
|
||
|
rts
|
||
|
|
||
|
*
|
||
|
* Destination remained denormalized. Call t_excdnrm with
|
||
|
* exceptional operand in ETEMP. MOVED EXC OP TO FPTEMP <2/8/91, JPO>
|
||
|
*
|
||
|
dst_fin:
|
||
|
tst.b L_SCR1(a6) ;check for sign
|
||
|
beq.b dst_exit
|
||
|
or.l #neg_mask,USER_FPSR(a6) ;set N
|
||
|
or.l #$8000,d1
|
||
|
dst_exit:
|
||
|
;;; movem.w d1,ETEMP_EX(a6) ; DELETED <2/8/91, JPO>
|
||
|
;;; movem.l d2,ETEMP_HI(a6) ; DELETED <2/8/91, JPO>
|
||
|
;;; movem.l d3,ETEMP_LO(a6) ; DELETED <2/8/91, JPO>
|
||
|
movem.w d1,FPTEMP_EX(a6) ; result in FPTEMP <2/8/91, JPO>
|
||
|
movem.l d2,FPTEMP_HI(a6) ; <2/8/91, JPO>
|
||
|
movem.l d3,FPTEMP_LO(a6) ; <2/8/91, JPO>
|
||
|
or.l #unfl_mask,USER_FPSR(a6) ;set unfl
|
||
|
movem.l (a7)+,d2/d3
|
||
|
;;; lea.l ETEMP(a6),a0 ; DELETED <2/8/91, JPO>
|
||
|
lea.l FPTEMP(a6),a0 ; point to result <2/8/91, JPO>
|
||
|
bra t_resdnrm
|
||
|
|
||
|
*
|
||
|
* Source is outside of 2^14 range. Test the sign and branch
|
||
|
* to the appropriate exception handler.
|
||
|
*
|
||
|
src_out:
|
||
|
tst.b L_SCR1(a6)
|
||
|
beq.b scro_pos
|
||
|
or.l #$8000,d1
|
||
|
scro_pos:
|
||
|
move.l FPTEMP_HI(a6),ETEMP_HI(a6)
|
||
|
move.l FPTEMP_LO(a6),ETEMP_LO(a6)
|
||
|
tst.w ETEMP(a6)
|
||
|
blt.b res_neg
|
||
|
;res_pos: ; label not referenced <1/7/91, JPO>
|
||
|
move.w d1,ETEMP(a6) ;result in ETEMP
|
||
|
bra t_ovfl2
|
||
|
res_neg:
|
||
|
move.w d1,ETEMP(a6) ;result in ETEMP
|
||
|
lea.l ETEMP(a6),a0
|
||
|
bra t_unfl
|
||
|
|
||
|
|