Home | History | Annotate | Line # | Download | only in fpsp
      1 *	$NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 cgd Exp $
      2 
      3 *	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
      4 *	M68000 Hi-Performance Microprocessor Division
      5 *	M68040 Software Package 
      6 *
      7 *	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
      8 *	All rights reserved.
      9 *
     10 *	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
     11 *	To the maximum extent permitted by applicable law,
     12 *	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
     13 *	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
     14 *	PARTICULAR PURPOSE and any warranty against infringement with
     15 *	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
     16 *	and any accompanying written materials. 
     17 *
     18 *	To the maximum extent permitted by applicable law,
     19 *	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
     20 *	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
     21 *	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
     22 *	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
     23 *	SOFTWARE.  Motorola assumes no responsibility for the maintenance
     24 *	and support of the SOFTWARE.  
     25 *
     26 *	You are hereby granted a copyright license to use, modify, and
     27 *	distribute the SOFTWARE so long as this entire notice is retained
     28 *	without alteration in any modified and/or redistributed versions,
     29 *	and that such modified versions are clearly identified as such.
     30 *	No licenses are granted by implication, estoppel or otherwise
     31 *	under any patents or trademarks of Motorola, Inc.
     32 
     33 *
     34 *	scale.sa 3.3 7/30/91
     35 *
     36 *	The entry point sSCALE computes the destination operand
     37 *	scaled by the source operand.  If the absoulute value of
     38 *	the source operand is (>= 2^14) an overflow or underflow
     39 *	is returned.
     40 *
     41 *	The entry point sscale is called from do_func to emulate
     42 *	the fscale unimplemented instruction.
     43 *
     44 *	Input: Double-extended destination operand in FPTEMP, 
     45 *		double-extended source operand in ETEMP.
     46 *
     47 *	Output: The function returns scale(X,Y) to fp0.
     48 *
     49 *	Modifies: fp0.
     50 *
     51 *	Algorithm:
     52 *		
     53 
     54 SCALE    IDNT    2,1 Motorola 040 Floating Point Software Package
     55 
     56 	section	8
     57 
     58 	include	fpsp.h
     59 
     60 	xref	t_ovfl2
     61 	xref	t_unfl
     62 	xref	round
     63 	xref	t_resdnrm
     64 
     65 SRC_BNDS dc.w	$3fff,$400c
     66 
     67 *
     68 * This entry point is used by the unimplemented instruction exception
     69 * handler.
     70 *
     71 *
     72 *
     73 *	FSCALE
     74 *
     75 	xdef	sscale
     76 sscale:
     77 	fmove.l		#0,fpcr		;clr user enabled exc
     78 	clr.l		d1
     79 	move.w		FPTEMP(a6),d1	;get dest exponent
     80 	smi		L_SCR1(a6)	;use L_SCR1 to hold sign
     81 	andi.l		#$7fff,d1	;strip sign
     82 	move.w		ETEMP(a6),d0	;check src bounds
     83 	andi.w		#$7fff,d0	;clr sign bit
     84 	cmp2.w		SRC_BNDS,d0
     85 	bcc.b		src_in
     86 	cmpi.w		#$400c,d0	;test for too large
     87 	bge.w		src_out
     88 *
     89 * The source input is below 1, so we check for denormalized numbers
     90 * and set unfl.
     91 *
     92 src_small:
     93 	move.b		DTAG(a6),d0
     94 	andi.b		#$e0,d0
     95 	tst.b		d0
     96 	beq.b		no_denorm
     97 	st		STORE_FLG(a6)	;dest already contains result
     98 	or.l		#unfl_mask,USER_FPSR(a6) ;set UNFL
     99 den_done:
    100 	lea.l		FPTEMP(a6),a0
    101 	bra		t_resdnrm
    102 no_denorm:
    103 	fmove.l		USER_FPCR(a6),FPCR
    104 	fmove.x		FPTEMP(a6),fp0	;simply return dest
    105 	rts
    106 
    107 
    108 *
    109 * Source is within 2^14 range.  To perform the int operation,
    110 * move it to d0.
    111 *
    112 src_in:
    113 	fmove.x		ETEMP(a6),fp0	;move in src for int
    114 	fmove.l		#rz_mode,fpcr	;force rz for src conversion
    115 	fmove.l		fp0,d0		;int src to d0
    116 	fmove.l		#0,FPSR		;clr status from above
    117 	tst.w		ETEMP(a6)	;check src sign
    118 	blt.w		src_neg
    119 *
    120 * Source is positive.  Add the src to the dest exponent.
    121 * The result can be denormalized, if src = 0, or overflow,
    122 * if the result of the add sets a bit in the upper word.
    123 *
    124 src_pos:
    125 	tst.w		d1		;check for denorm
    126 	beq.w		dst_dnrm
    127 	add.l		d0,d1		;add src to dest exp
    128 	beq.b		denorm		;if zero, result is denorm
    129 	cmpi.l		#$7fff,d1	;test for overflow
    130 	bge.b		ovfl
    131 	tst.b		L_SCR1(a6)
    132 	beq.b		spos_pos
    133 	or.w		#$8000,d1
    134 spos_pos:
    135 	move.w		d1,FPTEMP(a6)	;result in FPTEMP
    136 	fmove.l		USER_FPCR(a6),FPCR
    137 	fmove.x		FPTEMP(a6),fp0	;write result to fp0
    138 	rts
    139 ovfl:
    140 	tst.b		L_SCR1(a6)
    141 	beq.b		sovl_pos
    142 	or.w		#$8000,d1
    143 sovl_pos:
    144 	move.w		FPTEMP(a6),ETEMP(a6)	;result in ETEMP
    145 	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
    146 	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
    147 	bra		t_ovfl2
    148 
    149 denorm:
    150 	tst.b		L_SCR1(a6)
    151 	beq.b		den_pos
    152 	or.w		#$8000,d1
    153 den_pos:
    154 	tst.l		FPTEMP_HI(a6)	;check j bit
    155 	blt.b		nden_exit	;if set, not denorm
    156 	move.w		d1,ETEMP(a6)	;input expected in ETEMP
    157 	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
    158 	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
    159 	or.l		#unfl_bit,USER_FPSR(a6)	;set unfl
    160 	lea.l		ETEMP(a6),a0
    161 	bra		t_resdnrm
    162 nden_exit:
    163 	move.w		d1,FPTEMP(a6)	;result in FPTEMP
    164 	fmove.l		USER_FPCR(a6),FPCR
    165 	fmove.x		FPTEMP(a6),fp0	;write result to fp0
    166 	rts
    167 
    168 *
    169 * Source is negative.  Add the src to the dest exponent.
    170 * (The result exponent will be reduced).  The result can be
    171 * denormalized.
    172 *
    173 src_neg:
    174 	add.l		d0,d1		;add src to dest
    175 	beq.b		denorm		;if zero, result is denorm
    176 	blt.b		fix_dnrm	;if negative, result is 
    177 *					;needing denormalization
    178 	tst.b		L_SCR1(a6)
    179 	beq.b		sneg_pos
    180 	or.w		#$8000,d1
    181 sneg_pos:
    182 	move.w		d1,FPTEMP(a6)	;result in FPTEMP
    183 	fmove.l		USER_FPCR(a6),FPCR
    184 	fmove.x		FPTEMP(a6),fp0	;write result to fp0
    185 	rts
    186 
    187 
    188 *
    189 * The result exponent is below denorm value.  Test for catastrophic
    190 * underflow and force zero if true.  If not, try to shift the 
    191 * mantissa right until a zero exponent exists.
    192 *
    193 fix_dnrm:
    194 	cmpi.w		#$ffc0,d1	;lower bound for normalization
    195 	blt.w		fix_unfl	;if lower, catastrophic unfl
    196 	move.w		d1,d0		;use d0 for exp
    197 	move.l		d2,-(a7)	;free d2 for norm
    198 	move.l		FPTEMP_HI(a6),d1
    199 	move.l		FPTEMP_LO(a6),d2
    200 	clr.l		L_SCR2(a6)
    201 fix_loop:
    202 	add.w		#1,d0		;drive d0 to 0
    203 	lsr.l		#1,d1		;while shifting the
    204 	roxr.l		#1,d2		;mantissa to the right
    205 	bcc.b		no_carry
    206 	st		L_SCR2(a6)	;use L_SCR2 to capture inex
    207 no_carry:
    208 	tst.w		d0		;it is finished when
    209 	blt.b		fix_loop	;d0 is zero or the mantissa
    210 	tst.b		L_SCR2(a6)
    211 	beq.b		tst_zero
    212 	or.l		#unfl_inx_mask,USER_FPSR(a6)
    213 *					;set unfl, aunfl, ainex
    214 *
    215 * Test for zero. If zero, simply use fmove to return +/- zero
    216 * to the fpu.
    217 *
    218 tst_zero:
    219 	clr.w		FPTEMP_EX(a6)
    220 	tst.b		L_SCR1(a6)	;test for sign
    221 	beq.b		tst_con
    222 	or.w		#$8000,FPTEMP_EX(a6) ;set sign bit
    223 tst_con:
    224 	move.l		d1,FPTEMP_HI(a6)
    225 	move.l		d2,FPTEMP_LO(a6)
    226 	move.l		(a7)+,d2
    227 	tst.l		d1
    228 	bne.b		not_zero
    229 	tst.l		FPTEMP_LO(a6)
    230 	bne.b		not_zero
    231 *
    232 * Result is zero.  Check for rounding mode to set lsb.  If the
    233 * mode is rp, and the zero is positive, return smallest denorm.
    234 * If the mode is rm, and the zero is negative, return smallest
    235 * negative denorm.
    236 *
    237 	btst.b		#5,FPCR_MODE(a6) ;test if rm or rp
    238 	beq.b		no_dir
    239 	btst.b		#4,FPCR_MODE(a6) ;check which one
    240 	beq.b		zer_rm
    241 zer_rp:
    242 	tst.b		L_SCR1(a6)	;check sign
    243 	bne.b		no_dir		;if set, neg op, no inc
    244 	move.l		#1,FPTEMP_LO(a6) ;set lsb
    245 	bra.b		sm_dnrm
    246 zer_rm:
    247 	tst.b		L_SCR1(a6)	;check sign
    248 	beq.b		no_dir		;if clr, neg op, no inc
    249 	move.l		#1,FPTEMP_LO(a6) ;set lsb
    250 	or.l		#neg_mask,USER_FPSR(a6) ;set N
    251 	bra.b		sm_dnrm
    252 no_dir:
    253 	fmove.l		USER_FPCR(a6),FPCR
    254 	fmove.x		FPTEMP(a6),fp0	;use fmove to set cc's
    255 	rts
    256 
    257 *
    258 * The rounding mode changed the zero to a smallest denorm. Call 
    259 * t_resdnrm with exceptional operand in ETEMP.
    260 *
    261 sm_dnrm:
    262 	move.l		FPTEMP_EX(a6),ETEMP_EX(a6)
    263 	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
    264 	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
    265 	lea.l		ETEMP(a6),a0
    266 	bra		t_resdnrm
    267 
    268 *
    269 * Result is still denormalized.
    270 *
    271 not_zero:
    272 	or.l		#unfl_mask,USER_FPSR(a6) ;set unfl
    273 	tst.b		L_SCR1(a6)	;check for sign
    274 	beq.b		fix_exit
    275 	or.l		#neg_mask,USER_FPSR(a6) ;set N
    276 fix_exit:
    277 	bra.b		sm_dnrm
    278 
    279 	
    280 *
    281 * The result has underflowed to zero. Return zero and set
    282 * unfl, aunfl, and ainex.
    283 *
    284 fix_unfl:
    285 	or.l		#unfl_inx_mask,USER_FPSR(a6)
    286 	btst.b		#5,FPCR_MODE(a6) ;test if rm or rp
    287 	beq.b		no_dir2
    288 	btst.b		#4,FPCR_MODE(a6) ;check which one
    289 	beq.b		zer_rm2
    290 zer_rp2:
    291 	tst.b		L_SCR1(a6)	;check sign
    292 	bne.b		no_dir2		;if set, neg op, no inc
    293 	clr.l		FPTEMP_EX(a6)
    294 	clr.l		FPTEMP_HI(a6)
    295 	move.l		#1,FPTEMP_LO(a6) ;set lsb
    296 	bra.b		sm_dnrm		;return smallest denorm
    297 zer_rm2:
    298 	tst.b		L_SCR1(a6)	;check sign
    299 	beq.b		no_dir2		;if clr, neg op, no inc
    300 	move.w		#$8000,FPTEMP_EX(a6)
    301 	clr.l		FPTEMP_HI(a6)
    302 	move.l		#1,FPTEMP_LO(a6) ;set lsb
    303 	or.l		#neg_mask,USER_FPSR(a6) ;set N
    304 	bra.w		sm_dnrm		;return smallest denorm
    305 
    306 no_dir2:
    307 	tst.b		L_SCR1(a6)
    308 	bge.b		pos_zero
    309 neg_zero:
    310 	clr.l		FP_SCR1(a6)	;clear the exceptional operand
    311 	clr.l		FP_SCR1+4(a6)	;for gen_except.
    312 	clr.l		FP_SCR1+8(a6)
    313 	fmove.s		#:80000000,fp0	
    314 	rts
    315 pos_zero:
    316 	clr.l		FP_SCR1(a6)	;clear the exceptional operand
    317 	clr.l		FP_SCR1+4(a6)	;for gen_except.
    318 	clr.l		FP_SCR1+8(a6)
    319 	fmove.s		#:00000000,fp0
    320 	rts
    321 
    322 *
    323 * The destination is a denormalized number.  It must be handled
    324 * by first shifting the bits in the mantissa until it is normalized,
    325 * then adding the remainder of the source to the exponent.
    326 *
    327 dst_dnrm:
    328 	movem.l		d2/d3,-(a7)	
    329 	move.w		FPTEMP_EX(a6),d1
    330 	move.l		FPTEMP_HI(a6),d2
    331 	move.l		FPTEMP_LO(a6),d3
    332 dst_loop:
    333 	tst.l		d2		;test for normalized result
    334 	blt.b		dst_norm	;exit loop if so
    335 	tst.l		d0		;otherwise, test shift count
    336 	beq.b		dst_fin		;if zero, shifting is done
    337 	subq.l		#1,d0		;dec src
    338 	add.l		d3,d3
    339 	addx.l		d2,d2
    340 	bra.b		dst_loop
    341 *
    342 * Destination became normalized.  Simply add the remaining 
    343 * portion of the src to the exponent.
    344 *
    345 dst_norm:
    346 	add.w		d0,d1		;dst is normalized; add src
    347 	tst.b		L_SCR1(a6)
    348 	beq.b		dnrm_pos
    349 	or.w		#$8000,d1
    350 dnrm_pos:
    351 	movem.w		d1,FPTEMP_EX(a6)
    352 	movem.l		d2,FPTEMP_HI(a6)
    353 	movem.l		d3,FPTEMP_LO(a6)
    354 	fmove.l		USER_FPCR(a6),FPCR
    355 	fmove.x		FPTEMP(a6),fp0
    356 	movem.l		(a7)+,d2/d3
    357 	rts
    358 
    359 *
    360 * Destination remained denormalized.  Call t_excdnrm with
    361 * exceptional operand in ETEMP.
    362 *
    363 dst_fin:
    364 	tst.b		L_SCR1(a6)	;check for sign
    365 	beq.b		dst_exit
    366 	or.l		#neg_mask,USER_FPSR(a6) ;set N
    367 	or.w		#$8000,d1
    368 dst_exit:
    369 	movem.w		d1,ETEMP_EX(a6)
    370 	movem.l		d2,ETEMP_HI(a6)
    371 	movem.l		d3,ETEMP_LO(a6)
    372 	or.l		#unfl_mask,USER_FPSR(a6) ;set unfl
    373 	movem.l		(a7)+,d2/d3
    374 	lea.l		ETEMP(a6),a0
    375 	bra		t_resdnrm
    376 
    377 *
    378 * Source is outside of 2^14 range.  Test the sign and branch
    379 * to the appropriate exception handler.
    380 *
    381 src_out:
    382 	tst.b		L_SCR1(a6)
    383 	beq.b		scro_pos
    384 	or.w		#$8000,d1
    385 scro_pos:
    386 	move.l		FPTEMP_HI(a6),ETEMP_HI(a6)
    387 	move.l		FPTEMP_LO(a6),ETEMP_LO(a6)
    388 	tst.w		ETEMP(a6)
    389 	blt.b		res_neg
    390 res_pos:
    391 	move.w		d1,ETEMP(a6)	;result in ETEMP
    392 	bra		t_ovfl2
    393 res_neg:
    394 	move.w		d1,ETEMP(a6)	;result in ETEMP
    395 	lea.l		ETEMP(a6),a0
    396 	bra		t_unfl
    397 	end
    398