util.sa revision 1.4
11.4Sbriggs*	$NetBSD: util.sa,v 1.4 2001/12/09 01:43:13 briggs 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*	util.sa 3.7 7/29/91
351.1Smycroft*
361.1Smycroft*	This file contains routines used by other programs.
371.1Smycroft*
381.1Smycroft*	ovf_res: used by overflow to force the correct
391.1Smycroft*		 result. ovf_r_k, ovf_r_x2, ovf_r_x3 are 
401.1Smycroft*		 derivatives of this routine.
411.1Smycroft*	get_fline: get user's opcode word
421.1Smycroft*	g_dfmtou: returns the destination format.
431.1Smycroft*	g_opcls: returns the opclass of the float instruction.
441.1Smycroft*	g_rndpr: returns the rounding precision. 
451.1Smycroft*	reg_dest: write byte, word, or long data to Dn
461.1Smycroft*
471.1Smycroft
481.1SmycroftUTIL	IDNT    2,1 Motorola 040 Floating Point Software Package
491.1Smycroft
501.1Smycroft	section	8
511.1Smycroft
521.1Smycroft	include	fpsp.h
531.1Smycroft
541.1Smycroft	xref	mem_read
551.1Smycroft
561.1Smycroft	xdef	g_dfmtou
571.1Smycroft	xdef	g_opcls
581.1Smycroft	xdef	g_rndpr
591.1Smycroft	xdef	get_fline
601.1Smycroft	xdef	reg_dest
611.1Smycroft
621.1Smycroft*
631.1Smycroft* Final result table for ovf_res. Note that the negative counterparts
641.1Smycroft* are unnecessary as ovf_res always returns the sign separately from
651.1Smycroft* the exponent.
661.1Smycroft*					;+inf
671.1SmycroftEXT_PINF	dc.l	$7fff0000,$00000000,$00000000,$00000000	
681.1Smycroft*					;largest +ext
691.1SmycroftEXT_PLRG	dc.l	$7ffe0000,$ffffffff,$ffffffff,$00000000	
701.1Smycroft*					;largest magnitude +sgl in ext
711.1SmycroftSGL_PLRG	dc.l	$407e0000,$ffffff00,$00000000,$00000000	
721.1Smycroft*					;largest magnitude +dbl in ext
731.1SmycroftDBL_PLRG	dc.l	$43fe0000,$ffffffff,$fffff800,$00000000	
741.1Smycroft*					;largest -ext
751.1Smycroft
761.1Smycrofttblovfl:
771.1Smycroft	dc.l	EXT_RN
781.1Smycroft	dc.l	EXT_RZ
791.1Smycroft	dc.l	EXT_RM
801.1Smycroft	dc.l	EXT_RP
811.1Smycroft	dc.l	SGL_RN
821.1Smycroft	dc.l	SGL_RZ
831.1Smycroft	dc.l	SGL_RM
841.1Smycroft	dc.l	SGL_RP
851.1Smycroft	dc.l	DBL_RN
861.1Smycroft	dc.l	DBL_RZ
871.1Smycroft	dc.l	DBL_RM
881.1Smycroft	dc.l	DBL_RP
891.1Smycroft	dc.l	error
901.1Smycroft	dc.l	error
911.1Smycroft	dc.l	error
921.1Smycroft	dc.l	error
931.1Smycroft
941.1Smycroft
951.1Smycroft*
961.1Smycroft*	ovf_r_k --- overflow result calculation
971.1Smycroft*
981.1Smycroft* This entry point is used by kernel_ex.  
991.1Smycroft*
1001.1Smycroft* This forces the destination precision to be extended
1011.1Smycroft*
1021.1Smycroft* Input:	operand in ETEMP
1031.1Smycroft* Output:	a result is in ETEMP (internal extended format)
1041.1Smycroft*
1051.1Smycroft	xdef	ovf_r_k
1061.1Smycroftovf_r_k:
1071.1Smycroft	lea	ETEMP(a6),a0	;a0 points to source operand	
1081.1Smycroft	bclr.b	#sign_bit,ETEMP_EX(a6)
1091.1Smycroft	sne	ETEMP_SGN(a6)	;convert to internal IEEE format
1101.1Smycroft
1111.1Smycroft*
1121.1Smycroft*	ovf_r_x2 --- overflow result calculation
1131.1Smycroft*
1141.1Smycroft* This entry point used by x_ovfl.  (opclass 0 and 2)
1151.1Smycroft*
1161.1Smycroft* Input		a0  points to an operand in the internal extended format
1171.1Smycroft* Output	a0  points to the result in the internal extended format
1181.1Smycroft*
1191.1Smycroft* This sets the round precision according to the user's FPCR unless the
1201.1Smycroft* instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
1211.1Smycroft* fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
1221.1Smycroft* If the instruction is fsgldiv of fsglmul, the rounding precision must be
1231.1Smycroft* extended.  If the instruction is not fsgldiv or fsglmul but a force-
1241.1Smycroft* precision instruction, the rounding precision is then set to the force
1251.1Smycroft* precision.
1261.1Smycroft
1271.1Smycroft	xdef	ovf_r_x2
1281.1Smycroftovf_r_x2:
1291.1Smycroft	btst.b	#E3,E_BYTE(a6)		;check for nu exception
1301.1Smycroft	beq.l	ovf_e1_exc		;it is cu exception
1311.1Smycroftovf_e3_exc:
1321.1Smycroft	move.w	CMDREG3B(a6),d0		;get the command word
1331.1Smycroft	andi.w	#$00000060,d0		;clear all bits except 6 and 5
1341.1Smycroft	cmpi.l	#$00000040,d0
1351.1Smycroft	beq.l	ovff_sgl		;force precision is single
1361.1Smycroft	cmpi.l	#$00000060,d0
1371.1Smycroft	beq.l	ovff_dbl		;force precision is double
1381.1Smycroft	move.w	CMDREG3B(a6),d0		;get the command word again
1391.1Smycroft	andi.l	#$7f,d0			;clear all except operation
1401.1Smycroft	cmpi.l	#$33,d0			
1411.1Smycroft	beq.l	ovf_fsgl		;fsglmul or fsgldiv
1421.1Smycroft	cmpi.l	#$30,d0
1431.1Smycroft	beq.l	ovf_fsgl		
1441.1Smycroft	bra	ovf_fpcr		;instruction is none of the above
1451.1Smycroft*					;use FPCR
1461.1Smycroftovf_e1_exc:
1471.1Smycroft	move.w	CMDREG1B(a6),d0		;get command word
1481.1Smycroft	andi.l	#$00000044,d0		;clear all bits except 6 and 2
1491.1Smycroft	cmpi.l	#$00000040,d0
1501.1Smycroft	beq.l	ovff_sgl		;the instruction is force single
1511.1Smycroft	cmpi.l	#$00000044,d0
1521.1Smycroft	beq.l	ovff_dbl		;the instruction is force double
1531.1Smycroft	move.w	CMDREG1B(a6),d0		;again get the command word
1541.1Smycroft	andi.l	#$0000007f,d0		;clear all except the op code
1551.1Smycroft	cmpi.l	#$00000027,d0
1561.1Smycroft	beq.l	ovf_fsgl		;fsglmul
1571.1Smycroft	cmpi.l 	#$00000024,d0
1581.1Smycroft	beq.l	ovf_fsgl		;fsgldiv
1591.1Smycroft	bra	ovf_fpcr		;none of the above, use FPCR
1601.1Smycroft* 
1611.1Smycroft*
1621.1Smycroft* Inst is either fsgldiv or fsglmul.  Force extended precision.
1631.1Smycroft*
1641.1Smycroftovf_fsgl:
1651.1Smycroft	clr.l	d0
1661.4Sbriggs	bra.b	short_ovf_res
1671.1Smycroft
1681.1Smycroftovff_sgl:
1691.1Smycroft	move.l	#$00000001,d0		;set single
1701.4Sbriggs	bra.b	short_ovf_res
1711.1Smycroftovff_dbl:
1721.1Smycroft	move.l	#$00000002,d0		;set double
1731.4Sbriggs	bra.b	short_ovf_res
1741.1Smycroft*
1751.1Smycroft* The precision is in the fpcr.
1761.1Smycroft*
1771.1Smycroftovf_fpcr:
1781.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0 ;set round precision
1791.4Sbriggs	bra.b	short_ovf_res
1801.1Smycroft	
1811.1Smycroft*
1821.1Smycroft*
1831.1Smycroft*	ovf_r_x3 --- overflow result calculation
1841.1Smycroft*
1851.1Smycroft* This entry point used by x_ovfl. (opclass 3 only)
1861.1Smycroft*
1871.1Smycroft* Input		a0  points to an operand in the internal extended format
1881.1Smycroft* Output	a0  points to the result in the internal extended format
1891.1Smycroft*
1901.1Smycroft* This sets the round precision according to the destination size.
1911.1Smycroft*
1921.1Smycroft	xdef	ovf_r_x3
1931.1Smycroftovf_r_x3:
1941.1Smycroft	bsr	g_dfmtou	;get dest fmt in d0{1:0}
1951.1Smycroft*				;for fmovout, the destination format
1961.1Smycroft*				;is the rounding precision
1971.1Smycroft
1981.1Smycroft*
1991.1Smycroft*	ovf_res --- overflow result calculation
2001.1Smycroft*
2011.1Smycroft* Input:
2021.1Smycroft*	a0 	points to operand in internal extended format
2031.1Smycroft* Output:
2041.1Smycroft*	a0 	points to result in internal extended format
2051.1Smycroft*
2061.1Smycroft	xdef	ovf_res
2071.1Smycroftovf_res:
2081.4Sbriggsshort_ovf_res:
2091.1Smycroft	lsl.l	#2,d0		;move round precision to d0{3:2}
2101.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1 ;set round mode
2111.1Smycroft	or.l	d1,d0		;index is fmt:mode in d0{3:0}
2121.1Smycroft	lea.l	tblovfl,a1	;load a1 with table address
2131.1Smycroft	move.l	(a1,d0*4),a1	;use d0 as index to the table
2141.1Smycroft	jmp	(a1)		;go to the correct routine
2151.1Smycroft*
2161.1Smycroft*case DEST_FMT = EXT
2171.1Smycroft*
2181.1SmycroftEXT_RN:
2191.1Smycroft	lea.l	EXT_PINF,a1	;answer is +/- infinity
2201.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
2211.1Smycroft	bra	set_sign	;now go set the sign	
2221.1SmycroftEXT_RZ:
2231.1Smycroft	lea.l	EXT_PLRG,a1	;answer is +/- large number
2241.1Smycroft	bra	set_sign	;now go set the sign
2251.1SmycroftEXT_RM:
2261.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2271.1Smycroft	beq.b	e_rm_pos
2281.1Smycrofte_rm_neg:
2291.1Smycroft	lea.l	EXT_PINF,a1	;answer is negative infinity
2301.1Smycroft	or.l	#neginf_mask,USER_FPSR(a6)
2311.1Smycroft	bra	end_ovfr
2321.1Smycrofte_rm_pos:
2331.1Smycroft	lea.l	EXT_PLRG,a1	;answer is large positive number
2341.1Smycroft	bra	end_ovfr
2351.1SmycroftEXT_RP:
2361.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2371.1Smycroft	beq.b	e_rp_pos
2381.1Smycrofte_rp_neg:
2391.1Smycroft	lea.l	EXT_PLRG,a1	;answer is large negative number
2401.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
2411.1Smycroft	bra	end_ovfr
2421.1Smycrofte_rp_pos:
2431.1Smycroft	lea.l	EXT_PINF,a1	;answer is positive infinity
2441.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
2451.1Smycroft	bra	end_ovfr
2461.1Smycroft*
2471.1Smycroft*case DEST_FMT = DBL
2481.1Smycroft*
2491.1SmycroftDBL_RN:
2501.1Smycroft	lea.l	EXT_PINF,a1	;answer is +/- infinity
2511.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
2521.1Smycroft	bra	set_sign
2531.1SmycroftDBL_RZ:
2541.1Smycroft	lea.l	DBL_PLRG,a1	;answer is +/- large number
2551.1Smycroft	bra	set_sign	;now go set the sign
2561.1SmycroftDBL_RM:
2571.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2581.1Smycroft	beq.b	d_rm_pos
2591.1Smycroftd_rm_neg:
2601.1Smycroft	lea.l	EXT_PINF,a1	;answer is negative infinity
2611.1Smycroft	or.l	#neginf_mask,USER_FPSR(a6)
2621.1Smycroft	bra	end_ovfr	;inf is same for all precisions (ext,dbl,sgl)
2631.1Smycroftd_rm_pos:
2641.1Smycroft	lea.l	DBL_PLRG,a1	;answer is large positive number
2651.1Smycroft	bra	end_ovfr
2661.1SmycroftDBL_RP:
2671.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2681.1Smycroft	beq.b	d_rp_pos
2691.1Smycroftd_rp_neg:
2701.1Smycroft	lea.l	DBL_PLRG,a1	;answer is large negative number
2711.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
2721.1Smycroft	bra	end_ovfr
2731.1Smycroftd_rp_pos:
2741.1Smycroft	lea.l	EXT_PINF,a1	;answer is positive infinity
2751.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
2761.1Smycroft	bra	end_ovfr
2771.1Smycroft*
2781.1Smycroft*case DEST_FMT = SGL
2791.1Smycroft*
2801.1SmycroftSGL_RN:
2811.1Smycroft	lea.l	EXT_PINF,a1	;answer is +/-  infinity
2821.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
2831.1Smycroft	bra.b	set_sign
2841.1SmycroftSGL_RZ:
2851.1Smycroft	lea.l	SGL_PLRG,a1	;anwer is +/- large number
2861.1Smycroft	bra.b	set_sign
2871.1SmycroftSGL_RM:
2881.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2891.1Smycroft	beq.b	s_rm_pos
2901.1Smycrofts_rm_neg:
2911.1Smycroft	lea.l	EXT_PINF,a1	;answer is negative infinity
2921.1Smycroft	or.l	#neginf_mask,USER_FPSR(a6)
2931.1Smycroft	bra.b	end_ovfr
2941.1Smycrofts_rm_pos:
2951.1Smycroft	lea.l	SGL_PLRG,a1	;answer is large positive number
2961.1Smycroft	bra.b	end_ovfr
2971.1SmycroftSGL_RP:
2981.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
2991.1Smycroft	beq.b	s_rp_pos
3001.1Smycrofts_rp_neg:
3011.1Smycroft	lea.l	SGL_PLRG,a1	;answer is large negative number
3021.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
3031.1Smycroft	bra.b	end_ovfr
3041.1Smycrofts_rp_pos:
3051.1Smycroft	lea.l	EXT_PINF,a1	;answer is postive infinity
3061.1Smycroft	bset.b	#inf_bit,FPSR_CC(a6)
3071.1Smycroft	bra.b	end_ovfr
3081.1Smycroft
3091.1Smycroftset_sign:
3101.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
3111.1Smycroft	beq.b	end_ovfr
3121.1Smycroftneg_sign:
3131.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
3141.1Smycroft
3151.1Smycroftend_ovfr:
3161.1Smycroft	move.w	LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign
3171.1Smycroft	move.l	LOCAL_HI(a1),LOCAL_HI(a0)
3181.1Smycroft	move.l	LOCAL_LO(a1),LOCAL_LO(a0)
3191.1Smycroft	rts
3201.1Smycroft
3211.1Smycroft
3221.1Smycroft*
3231.1Smycroft*	ERROR
3241.1Smycroft*
3251.1Smycrofterror:
3261.1Smycroft	rts
3271.1Smycroft*
3281.1Smycroft*	get_fline --- get f-line opcode of interrupted instruction
3291.1Smycroft*
3301.1Smycroft*	Returns opcode in the low word of d0.
3311.1Smycroft*
3321.1Smycroftget_fline:
3331.1Smycroft	move.l	USER_FPIAR(a6),a0	;opcode address
3341.2Smycroft	clr.l	-(a7)		;reserve a word on the stack
3351.1Smycroft	lea.l	2(a7),a1	;point to low word of temporary
3361.1Smycroft	move.l	#2,d0		;count
3371.1Smycroft	bsr.l	mem_read
3381.1Smycroft	move.l	(a7)+,d0
3391.1Smycroft	rts
3401.1Smycroft*
3411.1Smycroft* 	g_rndpr --- put rounding precision in d0{1:0}
3421.1Smycroft*	
3431.1Smycroft*	valid return codes are:
3441.1Smycroft*		00 - extended 
3451.1Smycroft*		01 - single
3461.1Smycroft*		10 - double
3471.1Smycroft*
3481.1Smycroft* begin
3491.1Smycroft* get rounding precision (cmdreg3b{6:5})
3501.1Smycroft* begin
3511.1Smycroft*  case	opclass = 011 (move out)
3521.1Smycroft*	get destination format - this is the also the rounding precision
3531.1Smycroft*
3541.1Smycroft*  case	opclass = 0x0
3551.1Smycroft*	if E3
3561.1Smycroft*	    *case RndPr(from cmdreg3b{6:5} = 11  then RND_PREC = DBL
3571.1Smycroft*	    *case RndPr(from cmdreg3b{6:5} = 10  then RND_PREC = SGL
3581.1Smycroft*	     case RndPr(from cmdreg3b{6:5} = 00 | 01
3591.1Smycroft*		use precision from FPCR{7:6}
3601.1Smycroft*			case 00 then RND_PREC = EXT
3611.1Smycroft*			case 01 then RND_PREC = SGL
3621.1Smycroft*			case 10 then RND_PREC = DBL
3631.1Smycroft*	else E1
3641.1Smycroft*	     use precision in FPCR{7:6}
3651.1Smycroft*	     case 00 then RND_PREC = EXT
3661.1Smycroft*	     case 01 then RND_PREC = SGL
3671.1Smycroft*	     case 10 then RND_PREC = DBL
3681.1Smycroft* end
3691.1Smycroft*
3701.1Smycroftg_rndpr:
3711.1Smycroft	bsr.w	g_opcls		;get opclass in d0{2:0}
3721.1Smycroft	cmp.w	#$0003,d0	;check for opclass 011
3731.1Smycroft	bne.b	op_0x0
3741.1Smycroft
3751.1Smycroft*
3761.1Smycroft* For move out instructions (opclass 011) the destination format
3771.1Smycroft* is the same as the rounding precision.  Pass results from g_dfmtou.
3781.1Smycroft*
3791.1Smycroft	bsr.w 	g_dfmtou	
3801.1Smycroft	rts
3811.1Smycroftop_0x0:
3821.1Smycroft	btst.b	#E3,E_BYTE(a6)
3831.1Smycroft	beq.l	unf_e1_exc	;branch to e1 underflow
3841.1Smycroftunf_e3_exc:
3851.1Smycroft	move.l	CMDREG3B(a6),d0	;rounding precision in d0{10:9}
3861.1Smycroft	bfextu	d0{9:2},d0	;move the rounding prec bits to d0{1:0}
3871.1Smycroft	cmpi.l	#$2,d0
3881.1Smycroft	beq.l	unff_sgl	;force precision is single
3891.1Smycroft	cmpi.l	#$3,d0		;force precision is double
3901.1Smycroft	beq.l	unff_dbl
3911.1Smycroft	move.w	CMDREG3B(a6),d0	;get the command word again
3921.1Smycroft	andi.l	#$7f,d0		;clear all except operation
3931.1Smycroft	cmpi.l	#$33,d0			
3941.1Smycroft	beq.l	unf_fsgl	;fsglmul or fsgldiv
3951.1Smycroft	cmpi.l	#$30,d0
3961.1Smycroft	beq.l	unf_fsgl	;fsgldiv or fsglmul
3971.1Smycroft	bra	unf_fpcr
3981.1Smycroftunf_e1_exc:
3991.1Smycroft	move.l	CMDREG1B(a6),d0	;get 32 bits off the stack, 1st 16 bits
4001.1Smycroft*				;are the command word
4011.1Smycroft	andi.l	#$00440000,d0	;clear all bits except bits 6 and 2
4021.1Smycroft	cmpi.l	#$00400000,d0
4031.1Smycroft	beq.l	unff_sgl	;force single
4041.1Smycroft	cmpi.l	#$00440000,d0	;force double
4051.1Smycroft	beq.l	unff_dbl
4061.1Smycroft	move.l	CMDREG1B(a6),d0	;get the command word again
4071.1Smycroft	andi.l	#$007f0000,d0	;clear all bits except the operation
4081.1Smycroft	cmpi.l	#$00270000,d0
4091.1Smycroft	beq.l	unf_fsgl	;fsglmul
4101.1Smycroft	cmpi.l	#$00240000,d0
4111.1Smycroft	beq.l	unf_fsgl	;fsgldiv
4121.1Smycroft	bra	unf_fpcr
4131.1Smycroft
4141.1Smycroft*
4151.1Smycroft* Convert to return format.  The values from cmdreg3b and the return
4161.1Smycroft* values are:
4171.1Smycroft*	cmdreg3b	return	     precision
4181.1Smycroft*	--------	------	     ---------
4191.1Smycroft*	  00,01		  0		ext
4201.1Smycroft*	   10		  1		sgl
4211.1Smycroft*	   11		  2		dbl
4221.1Smycroft* Force single
4231.1Smycroft*
4241.1Smycroftunff_sgl:
4251.1Smycroft	move.l	#1,d0		;return 1
4261.1Smycroft	rts
4271.1Smycroft*
4281.1Smycroft* Force double
4291.1Smycroft*
4301.1Smycroftunff_dbl:
4311.1Smycroft	move.l	#2,d0		;return 2
4321.1Smycroft	rts
4331.1Smycroft*
4341.1Smycroft* Force extended
4351.1Smycroft*
4361.1Smycroftunf_fsgl:
4371.2Smycroft	clr.l	d0		
4381.1Smycroft	rts
4391.1Smycroft*
4401.1Smycroft* Get rounding precision set in FPCR{7:6}.
4411.1Smycroft*
4421.1Smycroftunf_fpcr:
4431.1Smycroft	move.l	USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6}
4441.1Smycroft	bfextu	d0{24:2},d0	;move the rounding prec bits to d0{1:0}
4451.1Smycroft	rts
4461.1Smycroft*
4471.1Smycroft*	g_opcls --- put opclass in d0{2:0}
4481.1Smycroft*
4491.1Smycroftg_opcls:
4501.1Smycroft	btst.b	#E3,E_BYTE(a6)
4511.1Smycroft	beq.b	opc_1b		;if set, go to cmdreg1b
4521.1Smycroftopc_3b:
4531.1Smycroft	clr.l	d0		;if E3, only opclass 0x0 is possible
4541.1Smycroft	rts
4551.1Smycroftopc_1b:
4561.1Smycroft	move.l	CMDREG1B(a6),d0
4571.1Smycroft	bfextu	d0{0:3},d0	;shift opclass bits d0{31:29} to d0{2:0}
4581.1Smycroft	rts
4591.1Smycroft*
4601.1Smycroft*	g_dfmtou --- put destination format in d0{1:0}
4611.1Smycroft*
4621.1Smycroft*	If E1, the format is from cmdreg1b{12:10}
4631.1Smycroft*	If E3, the format is extended.
4641.1Smycroft*
4651.1Smycroft*	Dest. Fmt.	
4661.1Smycroft*		extended  010 -> 00
4671.1Smycroft*		single    001 -> 01
4681.1Smycroft*		double    101 -> 10
4691.1Smycroft*
4701.1Smycroftg_dfmtou:
4711.1Smycroft	btst.b	#E3,E_BYTE(a6)
4721.1Smycroft	beq.b	op011
4731.1Smycroft	clr.l	d0		;if E1, size is always ext
4741.1Smycroft	rts
4751.1Smycroftop011:
4761.1Smycroft	move.l	CMDREG1B(a6),d0
4771.1Smycroft	bfextu	d0{3:3},d0	;dest fmt from cmdreg1b{12:10}
4781.1Smycroft	cmp.b	#1,d0		;check for single
4791.1Smycroft	bne.b	not_sgl
4801.1Smycroft	move.l	#1,d0
4811.1Smycroft	rts
4821.1Smycroftnot_sgl:
4831.1Smycroft	cmp.b	#5,d0		;check for double
4841.1Smycroft	bne.b	not_dbl
4851.1Smycroft	move.l	#2,d0
4861.1Smycroft	rts
4871.1Smycroftnot_dbl:
4881.1Smycroft	clr.l	d0		;must be extended
4891.1Smycroft	rts
4901.1Smycroft
4911.1Smycroft*
4921.1Smycroft*
4931.1Smycroft* Final result table for unf_sub. Note that the negative counterparts
4941.1Smycroft* are unnecessary as unf_sub always returns the sign separately from
4951.1Smycroft* the exponent.
4961.1Smycroft*					;+zero
4971.1SmycroftEXT_PZRO	dc.l	$00000000,$00000000,$00000000,$00000000	
4981.1Smycroft*					;+zero
4991.1SmycroftSGL_PZRO	dc.l	$3f810000,$00000000,$00000000,$00000000	
5001.1Smycroft*					;+zero
5011.1SmycroftDBL_PZRO	dc.l	$3c010000,$00000000,$00000000,$00000000	
5021.1Smycroft*					;smallest +ext denorm
5031.1SmycroftEXT_PSML	dc.l	$00000000,$00000000,$00000001,$00000000	
5041.1Smycroft*					;smallest +sgl denorm
5051.1SmycroftSGL_PSML	dc.l	$3f810000,$00000100,$00000000,$00000000	
5061.1Smycroft*					;smallest +dbl denorm
5071.1SmycroftDBL_PSML	dc.l	$3c010000,$00000000,$00000800,$00000000	
5081.1Smycroft*
5091.1Smycroft*	UNF_SUB --- underflow result calculation
5101.1Smycroft*
5111.1Smycroft* Input:
5121.1Smycroft*	d0 	contains round precision
5131.1Smycroft*	a0	points to input operand in the internal extended format
5141.1Smycroft*
5151.1Smycroft* Output:
5161.1Smycroft*	a0 	points to correct internal extended precision result.
5171.1Smycroft*
5181.1Smycroft
5191.1Smycrofttblunf:
5201.1Smycroft	dc.l	uEXT_RN
5211.1Smycroft	dc.l	uEXT_RZ
5221.1Smycroft	dc.l	uEXT_RM
5231.1Smycroft	dc.l	uEXT_RP
5241.1Smycroft	dc.l	uSGL_RN
5251.1Smycroft	dc.l	uSGL_RZ
5261.1Smycroft	dc.l	uSGL_RM
5271.1Smycroft	dc.l	uSGL_RP
5281.1Smycroft	dc.l	uDBL_RN
5291.1Smycroft	dc.l	uDBL_RZ
5301.1Smycroft	dc.l	uDBL_RM
5311.1Smycroft	dc.l	uDBL_RP
5321.1Smycroft	dc.l	uDBL_RN
5331.1Smycroft	dc.l	uDBL_RZ
5341.1Smycroft	dc.l	uDBL_RM
5351.1Smycroft	dc.l	uDBL_RP
5361.1Smycroft
5371.1Smycroft	xdef	unf_sub
5381.1Smycroftunf_sub:
5391.1Smycroft	lsl.l	#2,d0		;move round precision to d0{3:2}
5401.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1 ;set round mode
5411.1Smycroft	or.l	d1,d0		;index is fmt:mode in d0{3:0}
5421.1Smycroft	lea.l	tblunf,a1	;load a1 with table address
5431.1Smycroft	move.l	(a1,d0*4),a1	;use d0 as index to the table
5441.1Smycroft	jmp	(a1)		;go to the correct routine
5451.1Smycroft*
5461.1Smycroft*case DEST_FMT = EXT
5471.1Smycroft*
5481.1SmycroftuEXT_RN:
5491.1Smycroft	lea.l	EXT_PZRO,a1	;answer is +/- zero
5501.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5511.1Smycroft	bra	uset_sign	;now go set the sign	
5521.1SmycroftuEXT_RZ:
5531.1Smycroft	lea.l	EXT_PZRO,a1	;answer is +/- zero
5541.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5551.1Smycroft	bra	uset_sign	;now go set the sign
5561.1SmycroftuEXT_RM:
5571.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative underflow
5581.1Smycroft	beq.b	ue_rm_pos
5591.1Smycroftue_rm_neg:
5601.1Smycroft	lea.l	EXT_PSML,a1	;answer is negative smallest denorm
5611.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
5621.1Smycroft	bra	end_unfr
5631.1Smycroftue_rm_pos:
5641.1Smycroft	lea.l	EXT_PZRO,a1	;answer is positive zero
5651.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5661.1Smycroft	bra	end_unfr
5671.1SmycroftuEXT_RP:
5681.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative underflow
5691.1Smycroft	beq.b	ue_rp_pos
5701.1Smycroftue_rp_neg:
5711.1Smycroft	lea.l	EXT_PZRO,a1	;answer is negative zero
5721.1Smycroft	ori.l	#negz_mask,USER_FPSR(a6)
5731.1Smycroft	bra	end_unfr
5741.1Smycroftue_rp_pos:
5751.1Smycroft	lea.l	EXT_PSML,a1	;answer is positive smallest denorm
5761.1Smycroft	bra	end_unfr
5771.1Smycroft*
5781.1Smycroft*case DEST_FMT = DBL
5791.1Smycroft*
5801.1SmycroftuDBL_RN:
5811.1Smycroft	lea.l	DBL_PZRO,a1	;answer is +/- zero
5821.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5831.1Smycroft	bra	uset_sign
5841.1SmycroftuDBL_RZ:
5851.1Smycroft	lea.l	DBL_PZRO,a1	;answer is +/- zero
5861.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5871.1Smycroft	bra	uset_sign	;now go set the sign
5881.1SmycroftuDBL_RM:
5891.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
5901.1Smycroft	beq.b	ud_rm_pos
5911.1Smycroftud_rm_neg:
5921.1Smycroft	lea.l	DBL_PSML,a1	;answer is smallest denormalized negative
5931.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
5941.1Smycroft	bra	end_unfr
5951.1Smycroftud_rm_pos:
5961.1Smycroft	lea.l	DBL_PZRO,a1	;answer is positive zero
5971.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
5981.1Smycroft	bra	end_unfr
5991.1SmycroftuDBL_RP:
6001.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
6011.1Smycroft	beq.b	ud_rp_pos
6021.1Smycroftud_rp_neg:
6031.1Smycroft	lea.l	DBL_PZRO,a1	;answer is negative zero
6041.1Smycroft	ori.l	#negz_mask,USER_FPSR(a6)
6051.1Smycroft	bra	end_unfr
6061.1Smycroftud_rp_pos:
6071.1Smycroft	lea.l	DBL_PSML,a1	;answer is smallest denormalized negative
6081.1Smycroft	bra	end_unfr
6091.1Smycroft*
6101.1Smycroft*case DEST_FMT = SGL
6111.1Smycroft*
6121.1SmycroftuSGL_RN:
6131.1Smycroft	lea.l	SGL_PZRO,a1	;answer is +/- zero
6141.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
6151.1Smycroft	bra.b	uset_sign
6161.1SmycroftuSGL_RZ:
6171.1Smycroft	lea.l	SGL_PZRO,a1	;answer is +/- zero
6181.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
6191.1Smycroft	bra.b	uset_sign
6201.1SmycroftuSGL_RM:
6211.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
6221.1Smycroft	beq.b	us_rm_pos
6231.1Smycroftus_rm_neg:
6241.1Smycroft	lea.l	SGL_PSML,a1	;answer is smallest denormalized negative
6251.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
6261.1Smycroft	bra.b	end_unfr
6271.1Smycroftus_rm_pos:
6281.1Smycroft	lea.l	SGL_PZRO,a1	;answer is positive zero
6291.1Smycroft	bset.b	#z_bit,FPSR_CC(a6)
6301.1Smycroft	bra.b	end_unfr
6311.1SmycroftuSGL_RP:
6321.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
6331.1Smycroft	beq.b	us_rp_pos
6341.1Smycroftus_rp_neg:
6351.1Smycroft	lea.l	SGL_PZRO,a1	;answer is negative zero
6361.1Smycroft	ori.l	#negz_mask,USER_FPSR(a6)
6371.1Smycroft	bra.b	end_unfr
6381.1Smycroftus_rp_pos:
6391.1Smycroft	lea.l	SGL_PSML,a1	;answer is smallest denormalized positive
6401.1Smycroft	bra.b	end_unfr
6411.1Smycroft
6421.1Smycroftuset_sign:
6431.1Smycroft	tst.b	LOCAL_SGN(a0)	;if negative overflow
6441.1Smycroft	beq.b	end_unfr
6451.1Smycroftuneg_sign:
6461.1Smycroft	bset.b	#neg_bit,FPSR_CC(a6)
6471.1Smycroft
6481.1Smycroftend_unfr:
6491.1Smycroft	move.w	LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign
6501.1Smycroft	move.l	LOCAL_HI(a1),LOCAL_HI(a0)
6511.1Smycroft	move.l	LOCAL_LO(a1),LOCAL_LO(a0)
6521.1Smycroft	rts
6531.1Smycroft*
6541.1Smycroft*	reg_dest --- write byte, word, or long data to Dn
6551.1Smycroft*
6561.1Smycroft*
6571.1Smycroft* Input:
6581.1Smycroft*	L_SCR1: Data 
6591.1Smycroft*	d1:     data size and dest register number formatted as:
6601.1Smycroft*
6611.1Smycroft*	32		5    4     3     2     1     0
6621.1Smycroft*       -----------------------------------------------
6631.1Smycroft*       |        0        |    Size   |  Dest Reg #   |
6641.1Smycroft*       -----------------------------------------------
6651.1Smycroft*
6661.1Smycroft*	Size is:
6671.1Smycroft*		0 - Byte
6681.1Smycroft*		1 - Word
6691.1Smycroft*		2 - Long/Single
6701.1Smycroft*
6711.1Smycroftpregdst:
6721.1Smycroft	dc.l	byte_d0
6731.1Smycroft	dc.l	byte_d1
6741.1Smycroft	dc.l	byte_d2
6751.1Smycroft	dc.l	byte_d3
6761.1Smycroft	dc.l	byte_d4
6771.1Smycroft	dc.l	byte_d5
6781.1Smycroft	dc.l	byte_d6
6791.1Smycroft	dc.l	byte_d7
6801.1Smycroft	dc.l	word_d0
6811.1Smycroft	dc.l	word_d1
6821.1Smycroft	dc.l	word_d2
6831.1Smycroft	dc.l	word_d3
6841.1Smycroft	dc.l	word_d4
6851.1Smycroft	dc.l	word_d5
6861.1Smycroft	dc.l	word_d6
6871.1Smycroft	dc.l	word_d7
6881.1Smycroft	dc.l	long_d0
6891.1Smycroft	dc.l	long_d1
6901.1Smycroft	dc.l	long_d2
6911.1Smycroft	dc.l	long_d3
6921.1Smycroft	dc.l	long_d4
6931.1Smycroft	dc.l	long_d5
6941.1Smycroft	dc.l	long_d6
6951.1Smycroft	dc.l	long_d7
6961.1Smycroft
6971.1Smycroftreg_dest:
6981.1Smycroft	lea.l	pregdst,a0
6991.1Smycroft	move.l	(a0,d1*4),a0
7001.1Smycroft	jmp	(a0)
7011.1Smycroft
7021.1Smycroftbyte_d0:
7031.1Smycroft	move.b	L_SCR1(a6),USER_D0+3(a6)
7041.1Smycroft	rts
7051.1Smycroftbyte_d1:
7061.1Smycroft	move.b	L_SCR1(a6),USER_D1+3(a6)
7071.1Smycroft	rts
7081.1Smycroftbyte_d2:
7091.1Smycroft	move.b	L_SCR1(a6),d2
7101.1Smycroft	rts
7111.1Smycroftbyte_d3:
7121.1Smycroft	move.b	L_SCR1(a6),d3
7131.1Smycroft	rts
7141.1Smycroftbyte_d4:
7151.1Smycroft	move.b	L_SCR1(a6),d4
7161.1Smycroft	rts
7171.1Smycroftbyte_d5:
7181.1Smycroft	move.b	L_SCR1(a6),d5
7191.1Smycroft	rts
7201.1Smycroftbyte_d6:
7211.1Smycroft	move.b	L_SCR1(a6),d6
7221.1Smycroft	rts
7231.1Smycroftbyte_d7:
7241.1Smycroft	move.b	L_SCR1(a6),d7
7251.1Smycroft	rts
7261.1Smycroftword_d0:
7271.1Smycroft	move.w	L_SCR1(a6),USER_D0+2(a6)
7281.1Smycroft	rts
7291.1Smycroftword_d1:
7301.1Smycroft	move.w	L_SCR1(a6),USER_D1+2(a6)
7311.1Smycroft	rts
7321.1Smycroftword_d2:
7331.1Smycroft	move.w	L_SCR1(a6),d2
7341.1Smycroft	rts
7351.1Smycroftword_d3:
7361.1Smycroft	move.w	L_SCR1(a6),d3
7371.1Smycroft	rts
7381.1Smycroftword_d4:
7391.1Smycroft	move.w	L_SCR1(a6),d4
7401.1Smycroft	rts
7411.1Smycroftword_d5:
7421.1Smycroft	move.w	L_SCR1(a6),d5
7431.1Smycroft	rts
7441.1Smycroftword_d6:
7451.1Smycroft	move.w	L_SCR1(a6),d6
7461.1Smycroft	rts
7471.1Smycroftword_d7:
7481.1Smycroft	move.w	L_SCR1(a6),d7
7491.1Smycroft	rts
7501.1Smycroftlong_d0:
7511.1Smycroft	move.l	L_SCR1(a6),USER_D0(a6)
7521.1Smycroft	rts
7531.1Smycroftlong_d1:
7541.1Smycroft	move.l	L_SCR1(a6),USER_D1(a6)
7551.1Smycroft	rts
7561.1Smycroftlong_d2:
7571.1Smycroft	move.l	L_SCR1(a6),d2
7581.1Smycroft	rts
7591.1Smycroftlong_d3:
7601.1Smycroft	move.l	L_SCR1(a6),d3
7611.1Smycroft	rts
7621.1Smycroftlong_d4:
7631.1Smycroft	move.l	L_SCR1(a6),d4
7641.1Smycroft	rts
7651.1Smycroftlong_d5:
7661.1Smycroft	move.l	L_SCR1(a6),d5
7671.1Smycroft	rts
7681.1Smycroftlong_d6:
7691.1Smycroft	move.l	L_SCR1(a6),d6
7701.1Smycroft	rts
7711.1Smycroftlong_d7:
7721.1Smycroft	move.l	L_SCR1(a6),d7
7731.1Smycroft	rts
7741.1Smycroft	end
775