x_unfl.sa revision 1.1
11.1Smycroft*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
21.1Smycroft*	M68000 Hi-Performance Microprocessor Division
31.1Smycroft*	M68040 Software Package 
41.1Smycroft*
51.1Smycroft*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
61.1Smycroft*	All rights reserved.
71.1Smycroft*
81.1Smycroft*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
91.1Smycroft*	To the maximum extent permitted by applicable law,
101.1Smycroft*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
111.1Smycroft*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
121.1Smycroft*	PARTICULAR PURPOSE and any warranty against infringement with
131.1Smycroft*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
141.1Smycroft*	and any accompanying written materials. 
151.1Smycroft*
161.1Smycroft*	To the maximum extent permitted by applicable law,
171.1Smycroft*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
181.1Smycroft*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
191.1Smycroft*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
201.1Smycroft*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
211.1Smycroft*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
221.1Smycroft*	and support of the SOFTWARE.  
231.1Smycroft*
241.1Smycroft*	You are hereby granted a copyright license to use, modify, and
251.1Smycroft*	distribute the SOFTWARE so long as this entire notice is retained
261.1Smycroft*	without alteration in any modified and/or redistributed versions,
271.1Smycroft*	and that such modified versions are clearly identified as such.
281.1Smycroft*	No licenses are granted by implication, estoppel or otherwise
291.1Smycroft*	under any patents or trademarks of Motorola, Inc.
301.1Smycroft
311.1Smycroft*
321.1Smycroft*	x_unfl.sa 3.4 7/1/91
331.1Smycroft*
341.1Smycroft*	fpsp_unfl --- FPSP handler for underflow exception
351.1Smycroft*
361.1Smycroft* Trap disabled results
371.1Smycroft*	For 881/2 compatibility, sw must denormalize the intermediate 
381.1Smycroft* result, then store the result.  Denormalization is accomplished 
391.1Smycroft* by taking the intermediate result (which is always normalized) and 
401.1Smycroft* shifting the mantissa right while incrementing the exponent until 
411.1Smycroft* it is equal to the denormalized exponent for the destination 
421.1Smycroft* format.  After denormalizatoin, the result is rounded to the 
431.1Smycroft* destination format.
441.1Smycroft*		
451.1Smycroft* Trap enabled results
461.1Smycroft* 	All trap disabled code applies.	In addition the exceptional 
471.1Smycroft* operand needs to made available to the user with a bias of $6000 
481.1Smycroft* added to the exponent.
491.1Smycroft*
501.1Smycroft
511.1SmycroftX_UNFL	IDNT    2,1 Motorola 040 Floating Point Software Package
521.1Smycroft
531.1Smycroft	section	8
541.1Smycroft
551.1Smycroft	include	fpsp.h
561.1Smycroft
571.1Smycroft	xref	denorm
581.1Smycroft	xref	round
591.1Smycroft	xref	store
601.1Smycroft	xref	g_rndpr
611.1Smycroft	xref	g_opcls
621.1Smycroft	xref	g_dfmtou
631.1Smycroft	xref	real_unfl
641.1Smycroft	xref	real_inex
651.1Smycroft	xref	fpsp_done
661.1Smycroft	xref	b1238_fix
671.1Smycroft
681.1Smycroft	xdef	fpsp_unfl
691.1Smycroftfpsp_unfl:
701.1Smycroft	link		a6,#-LOCAL_SIZE
711.1Smycroft	fsave		-(a7)
721.1Smycroft	movem.l		d0-d1/a0-a1,USER_DA(a6)
731.1Smycroft	fmovem.x	fp0-fp3,USER_FP0(a6)
741.1Smycroft	fmovem.l	fpcr/fpsr/fpiar,USER_FPCR(a6)
751.1Smycroft
761.1Smycroft*
771.1Smycroft	bsr.l		unf_res	;denormalize, round & store interm op
781.1Smycroft*
791.1Smycroft* If underflow exceptions are not enabled, check for inexact
801.1Smycroft* exception
811.1Smycroft*
821.1Smycroft	btst.b		#unfl_bit,FPCR_ENABLE(a6)
831.1Smycroft	beq.b		ck_inex
841.1Smycroft
851.1Smycroft	btst.b		#E3,E_BYTE(a6)
861.1Smycroft	beq.b		no_e3_1
871.1Smycroft*
881.1Smycroft* Clear dirty bit on dest resister in the frame before branching
891.1Smycroft* to b1238_fix.
901.1Smycroft*
911.1Smycroft	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
921.1Smycroft	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
931.1Smycroft	bsr.l		b1238_fix		;test for bug1238 case
941.1Smycroft	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
951.1Smycroft	or.l		#sx_mask,E_BYTE(a6)
961.1Smycroftno_e3_1:
971.1Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
981.1Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
991.1Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
1001.1Smycroft	frestore	(a7)+
1011.1Smycroft	unlk		a6
1021.1Smycroft	bra.l		real_unfl
1031.1Smycroft*
1041.1Smycroft* It is possible to have either inex2 or inex1 exceptions with the
1051.1Smycroft* unfl.  If the inex enable bit is set in the FPCR, and either
1061.1Smycroft* inex2 or inex1 occured, we must clean up and branch to the
1071.1Smycroft* real inex handler.
1081.1Smycroft*
1091.1Smycroftck_inex:
1101.1Smycroft	move.b		FPCR_ENABLE(a6),d0
1111.1Smycroft	and.b		FPSR_EXCEPT(a6),d0
1121.1Smycroft	andi.b		#$3,d0
1131.1Smycroft	beq.b		unfl_done
1141.1Smycroft
1151.1Smycroft*
1161.1Smycroft* Inexact enabled and reported, and we must take an inexact exception
1171.1Smycroft*	
1181.1Smycrofttake_inex:
1191.1Smycroft	btst.b		#E3,E_BYTE(a6)
1201.1Smycroft	beq.b		no_e3_2
1211.1Smycroft*
1221.1Smycroft* Clear dirty bit on dest resister in the frame before branching
1231.1Smycroft* to b1238_fix.
1241.1Smycroft*
1251.1Smycroft	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
1261.1Smycroft	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
1271.1Smycroft	bsr.l		b1238_fix		;test for bug1238 case
1281.1Smycroft	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
1291.1Smycroft	or.l		#sx_mask,E_BYTE(a6)
1301.1Smycroftno_e3_2:
1311.1Smycroft	move.b		#INEX_VEC,EXC_VEC+1(a6)
1321.1Smycroft	movem.l         USER_DA(a6),d0-d1/a0-a1
1331.1Smycroft	fmovem.x        USER_FP0(a6),fp0-fp3
1341.1Smycroft	fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
1351.1Smycroft	frestore        (a7)+
1361.1Smycroft	unlk            a6
1371.1Smycroft	bra.l		real_inex
1381.1Smycroft
1391.1Smycroftunfl_done:
1401.1Smycroft	bclr.b		#E3,E_BYTE(a6)
1411.1Smycroft	beq.b		e1_set		;if set then branch
1421.1Smycroft*
1431.1Smycroft* Clear dirty bit on dest resister in the frame before branching
1441.1Smycroft* to b1238_fix.
1451.1Smycroft*
1461.1Smycroft	bfextu		CMDREG3B(a6){6:3},d0		;get dest reg no
1471.1Smycroft	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
1481.1Smycroft	bsr.l		b1238_fix		;test for bug1238 case
1491.1Smycroft	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
1501.1Smycroft	or.l		#sx_mask,E_BYTE(a6)
1511.1Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
1521.1Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
1531.1Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
1541.1Smycroft	frestore	(a7)+
1551.1Smycroft	unlk		a6
1561.1Smycroft	bra.l		fpsp_done
1571.1Smycrofte1_set:
1581.1Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
1591.1Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
1601.1Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
1611.1Smycroft	unlk		a6
1621.1Smycroft	bra.l		fpsp_done
1631.1Smycroft*
1641.1Smycroft*	unf_res --- underflow result calculation
1651.1Smycroft*
1661.1Smycroftunf_res:
1671.1Smycroft	bsr.l		g_rndpr		;returns RND_PREC in d0 0=ext,
1681.1Smycroft*					;1=sgl, 2=dbl
1691.1Smycroft*					;we need the RND_PREC in the
1701.1Smycroft*					;upper word for round
1711.1Smycroft	move.w		#0,-(a7)	
1721.1Smycroft	move.w		d0,-(a7)	;copy RND_PREC to stack
1731.1Smycroft*
1741.1Smycroft*
1751.1Smycroft* If the exception bit set is E3, the exceptional operand from the
1761.1Smycroft* fpu is in WBTEMP; else it is in FPTEMP.
1771.1Smycroft*
1781.1Smycroft	btst.b		#E3,E_BYTE(a6)
1791.1Smycroft	beq.b		unf_E1
1801.1Smycroftunf_E3:
1811.1Smycroft	lea		WBTEMP(a6),a0	;a0 now points to operand
1821.1Smycroft*
1831.1Smycroft* Test for fsgldiv and fsglmul.  If the inst was one of these, then
1841.1Smycroft* force the precision to extended for the denorm routine.  Use
1851.1Smycroft* the user's precision for the round routine.
1861.1Smycroft*
1871.1Smycroft	move.w		CMDREG3B(a6),d1	;check for fsgldiv or fsglmul
1881.1Smycroft	andi.w		#$7f,d1
1891.1Smycroft	cmpi.w		#$30,d1		;check for sgldiv
1901.1Smycroft	beq.b		unf_sgl
1911.1Smycroft	cmpi.w		#$33,d1		;check for sglmul
1921.1Smycroft	bne.b		unf_cont	;if not, use fpcr prec in round
1931.1Smycroftunf_sgl:
1941.1Smycroft	clr.l		d0
1951.1Smycroft	move.w		#$1,(a7)	;override g_rndpr precision
1961.1Smycroft*					;force single
1971.1Smycroft	bra.b		unf_cont
1981.1Smycroftunf_E1:
1991.1Smycroft	lea		FPTEMP(a6),a0	;a0 now points to operand
2001.1Smycroftunf_cont:
2011.1Smycroft	bclr.b		#sign_bit,LOCAL_EX(a0)	;clear sign bit
2021.1Smycroft	sne		LOCAL_SGN(a0)		;store sign
2031.1Smycroft
2041.1Smycroft	bsr.l		denorm		;returns denorm, a0 points to it
2051.1Smycroft*
2061.1Smycroft* WARNING:
2071.1Smycroft*				;d0 has guard,round sticky bit
2081.1Smycroft*				;make sure that it is not corrupted
2091.1Smycroft*				;before it reaches the round subroutine
2101.1Smycroft*				;also ensure that a0 isn't corrupted
2111.1Smycroft
2121.1Smycroft*
2131.1Smycroft* Set up d1 for round subroutine d1 contains the PREC/MODE
2141.1Smycroft* information respectively on upper/lower register halves.
2151.1Smycroft*
2161.1Smycroft	bfextu		FPCR_MODE(a6){2:2},d1	;get mode from FPCR
2171.1Smycroft*						;mode in lower d1
2181.1Smycroft	add.l		(a7)+,d1		;merge PREC/MODE
2191.1Smycroft*
2201.1Smycroft* WARNING: a0 and d0 are assumed to be intact between the denorm and
2211.1Smycroft* round subroutines. All code between these two subroutines
2221.1Smycroft* must not corrupt a0 and d0.
2231.1Smycroft*
2241.1Smycroft*
2251.1Smycroft* Perform Round	
2261.1Smycroft*	Input:		a0 points to input operand
2271.1Smycroft*			d0{31:29} has guard, round, sticky
2281.1Smycroft*			d1{01:00} has rounding mode
2291.1Smycroft*			d1{17:16} has rounding precision
2301.1Smycroft*	Output:		a0 points to rounded operand
2311.1Smycroft*
2321.1Smycroft
2331.1Smycroft	bsr.l		round		;returns rounded denorm at (a0)
2341.1Smycroft*
2351.1Smycroft* Differentiate between store to memory vs. store to register
2361.1Smycroft*
2371.1Smycroftunf_store:
2381.1Smycroft	bsr.l		g_opcls		;returns opclass in d0{2:0}
2391.1Smycroft	cmpi.b		#$3,d0
2401.1Smycroft	bne.b		not_opc011
2411.1Smycroft*
2421.1Smycroft* At this point, a store to memory is pending
2431.1Smycroft*
2441.1Smycroftopc011:
2451.1Smycroft	bsr.l		g_dfmtou
2461.1Smycroft	tst.b		d0
2471.1Smycroft	beq.b		ext_opc011	;If extended, do not subtract
2481.1Smycroft* 				;If destination format is sgl/dbl, 
2491.1Smycroft	tst.b		LOCAL_HI(a0)	;If rounded result is normal,don't
2501.1Smycroft*					;subtract
2511.1Smycroft	bmi.b		ext_opc011
2521.1Smycroft	subq.w		#1,LOCAL_EX(a0)	;account for denorm bias vs.
2531.1Smycroft*				;normalized bias
2541.1Smycroft*				;          normalized   denormalized
2551.1Smycroft*				;single       $7f           $7e
2561.1Smycroft*				;double       $3ff          $3fe
2571.1Smycroft*
2581.1Smycroftext_opc011:
2591.1Smycroft	bsr.l		store		;stores to memory
2601.1Smycroft	bra.b		unf_done	;finish up
2611.1Smycroft
2621.1Smycroft*
2631.1Smycroft* At this point, a store to a float register is pending
2641.1Smycroft*
2651.1Smycroftnot_opc011:
2661.1Smycroft	bsr.l		store	;stores to float register
2671.1Smycroft*				;a0 is not corrupted on a store to a
2681.1Smycroft*				;float register.
2691.1Smycroft*
2701.1Smycroft* Set the condition codes according to result
2711.1Smycroft*
2721.1Smycroft	tst.l		LOCAL_HI(a0)	;check upper mantissa
2731.1Smycroft	bne.b		ck_sgn
2741.1Smycroft	tst.l		LOCAL_LO(a0)	;check lower mantissa
2751.1Smycroft	bne.b		ck_sgn
2761.1Smycroft	bset.b		#z_bit,FPSR_CC(a6) ;set condition codes if zero
2771.1Smycroftck_sgn:
2781.1Smycroft	btst.b 		#sign_bit,LOCAL_EX(a0)	;check the sign bit
2791.1Smycroft	beq.b		unf_done
2801.1Smycroft	bset.b		#neg_bit,FPSR_CC(a6)
2811.1Smycroft
2821.1Smycroft*
2831.1Smycroft* Finish.  
2841.1Smycroft*
2851.1Smycroftunf_done:
2861.1Smycroft	btst.b		#inex2_bit,FPSR_EXCEPT(a6)
2871.1Smycroft	beq.b		no_aunfl
2881.1Smycroft	bset.b		#aunfl_bit,FPSR_AEXCEPT(a6)
2891.1Smycroftno_aunfl:
2901.1Smycroft	rts
2911.1Smycroft
2921.1Smycroft	end
293