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