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