summaryrefslogtreecommitdiff
path: root/sys/arch/m68k/fpsp/scale.sa
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/m68k/fpsp/scale.sa
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/m68k/fpsp/scale.sa')
-rw-r--r--sys/arch/m68k/fpsp/scale.sa397
1 files changed, 397 insertions, 0 deletions
diff --git a/sys/arch/m68k/fpsp/scale.sa b/sys/arch/m68k/fpsp/scale.sa
new file mode 100644
index 00000000000..e94fded546d
--- /dev/null
+++ b/sys/arch/m68k/fpsp/scale.sa
@@ -0,0 +1,397 @@
+* $NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 cgd Exp $
+
+* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
+* M68000 Hi-Performance Microprocessor Division
+* M68040 Software Package
+*
+* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
+* All rights reserved.
+*
+* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
+* To the maximum extent permitted by applicable law,
+* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
+* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+* PARTICULAR PURPOSE and any warranty against infringement with
+* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
+* and any accompanying written materials.
+*
+* To the maximum extent permitted by applicable law,
+* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
+* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
+* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
+* SOFTWARE. Motorola assumes no responsibility for the maintenance
+* and support of the SOFTWARE.
+*
+* You are hereby granted a copyright license to use, modify, and
+* distribute the SOFTWARE so long as this entire notice is retained
+* without alteration in any modified and/or redistributed versions,
+* and that such modified versions are clearly identified as such.
+* No licenses are granted by implication, estoppel or otherwise
+* under any patents or trademarks of Motorola, Inc.
+
+*
+* scale.sa 3.3 7/30/91
+*
+* The entry point sSCALE computes the destination operand
+* scaled by the source operand. If the absoulute 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:
+*
+
+SCALE IDNT 2,1 Motorola 040 Floating Point Software Package
+
+ section 8
+
+ include fpsp.h
+
+ xref t_ovfl2
+ xref t_unfl
+ xref round
+ xref t_resdnrm
+
+SRC_BNDS dc.w $3fff,$400c
+
+*
+* This entry point is used by the unimplemented instruction exception
+* handler.
+*
+*
+*
+* FSCALE
+*
+ xdef sscale
+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:
+ move.b DTAG(a6),d0
+ andi.b #$e0,d0
+ tst.b d0
+ beq.b no_denorm
+ st STORE_FLG(a6) ;dest already contains result
+ or.l #unfl_mask,USER_FPSR(a6) ;set UNFL
+den_done:
+ 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:
+ tst.w d1 ;check for denorm
+ beq.w dst_dnrm
+ add.l d0,d1 ;add src to dest exp
+ beq.b denorm ;if zero, result is denorm
+ cmpi.l #$7fff,d1 ;test for overflow
+ bge.b ovfl
+ 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
+ovfl:
+ 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
+
+denorm:
+ 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
+ move.l FPTEMP_HI(a6),ETEMP_HI(a6)
+ move.l FPTEMP_LO(a6),ETEMP_LO(a6)
+ or.l #unfl_bit,USER_FPSR(a6) ;set unfl
+ lea.l ETEMP(a6),a0
+ 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 denorm ;if zero, result is denorm
+ 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
+ blt.w fix_unfl ;if lower, catastrophic unfl
+ move.w d1,d0 ;use d0 for exp
+ move.l d2,-(a7) ;free d2 for norm
+ move.l FPTEMP_HI(a6),d1
+ move.l FPTEMP_LO(a6),d2
+ clr.l L_SCR2(a6)
+fix_loop:
+ add.w #1,d0 ;drive d0 to 0
+ lsr.l #1,d1 ;while shifting the
+ roxr.l #1,d2 ;mantissa to the right
+ bcc.b no_carry
+ st L_SCR2(a6) ;use L_SCR2 to capture inex
+no_carry:
+ tst.w d0 ;it is finished when
+ blt.b fix_loop ;d0 is zero or the mantissa
+ tst.b L_SCR2(a6)
+ beq.b tst_zero
+ or.l #unfl_inx_mask,USER_FPSR(a6)
+* ;set unfl, aunfl, ainex
+*
+* Test for zero. If zero, simply use fmove to return +/- zero
+* to the fpu.
+*
+tst_zero:
+ clr.w FPTEMP_EX(a6)
+ tst.b L_SCR1(a6) ;test for sign
+ beq.b tst_con
+ or.w #$8000,FPTEMP_EX(a6) ;set sign bit
+tst_con:
+ move.l d1,FPTEMP_HI(a6)
+ move.l d2,FPTEMP_LO(a6)
+ move.l (a7)+,d2
+ tst.l d1
+ bne.b not_zero
+ tst.l FPTEMP_LO(a6)
+ bne.b not_zero
+*
+* 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
+ beq.b no_dir
+ btst.b #4,FPCR_MODE(a6) ;check which one
+ beq.b zer_rm
+zer_rp:
+ tst.b L_SCR1(a6) ;check sign
+ bne.b no_dir ;if set, neg op, no inc
+ move.l #1,FPTEMP_LO(a6) ;set lsb
+ bra.b sm_dnrm
+zer_rm:
+ tst.b L_SCR1(a6) ;check sign
+ beq.b no_dir ;if clr, neg op, no inc
+ move.l #1,FPTEMP_LO(a6) ;set lsb
+ or.l #neg_mask,USER_FPSR(a6) ;set N
+ bra.b sm_dnrm
+no_dir:
+ 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:
+ move.l FPTEMP_EX(a6),ETEMP_EX(a6)
+ move.l FPTEMP_HI(a6),ETEMP_HI(a6)
+ move.l FPTEMP_LO(a6),ETEMP_LO(a6)
+ lea.l ETEMP(a6),a0
+ bra t_resdnrm
+
+*
+* Result is still denormalized.
+*
+not_zero:
+ 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
+
+
+*
+* The result has underflowed to zero. Return zero and set
+* unfl, aunfl, and ainex.
+*
+fix_unfl:
+ 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:
+ 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 pos_zero
+neg_zero:
+ clr.l FP_SCR1(a6) ;clear the exceptional operand
+ clr.l FP_SCR1+4(a6) ;for gen_except.
+ clr.l FP_SCR1+8(a6)
+ fmove.s #:80000000,fp0
+ rts
+pos_zero:
+ clr.l FP_SCR1(a6) ;clear the exceptional operand
+ clr.l FP_SCR1+4(a6) ;for gen_except.
+ clr.l FP_SCR1+8(a6)
+ 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 d2 ;test for normalized result
+ blt.b dst_norm ;exit loop if so
+ tst.l d0 ;otherwise, test shift count
+ beq.b dst_fin ;if zero, shifting is done
+ subq.l #1,d0 ;dec src
+ add.l d3,d3
+ addx.l d2,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.w #$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.
+*
+dst_fin:
+ tst.b L_SCR1(a6) ;check for sign
+ beq.b dst_exit
+ or.l #neg_mask,USER_FPSR(a6) ;set N
+ or.w #$8000,d1
+dst_exit:
+ movem.w d1,ETEMP_EX(a6)
+ movem.l d2,ETEMP_HI(a6)
+ movem.l d3,ETEMP_LO(a6)
+ or.l #unfl_mask,USER_FPSR(a6) ;set unfl
+ movem.l (a7)+,d2/d3
+ lea.l ETEMP(a6),a0
+ 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.w #$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:
+ 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
+ end