res_func.sa revision 1.3
11.3Scgd*	$NetBSD: res_func.sa,v 1.3 1994/10/26 07:49:22 cgd 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*	res_func.sa 3.9 7/29/91
351.1Smycroft*
361.1Smycroft* Normalizes denormalized numbers if necessary and updates the
371.1Smycroft* stack frame.  The function is then restored back into the
381.1Smycroft* machine and the 040 completes the operation.  This routine
391.1Smycroft* is only used by the unsupported data type/format handler.
401.1Smycroft* (Exception vector 55).
411.1Smycroft*
421.1Smycroft* For packed move out (fmove.p fpm,<ea>) the operation is
431.1Smycroft* completed here; data is packed and moved to user memory. 
441.1Smycroft* The stack is restored to the 040 only in the case of a
451.1Smycroft* reportable exception in the conversion.
461.1Smycroft*
471.1Smycroft
481.1SmycroftRES_FUNC    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.1Smycroftsp_bnds:	dc.w	$3f81,$407e
551.1Smycroft		dc.w	$3f6a,$0000
561.1Smycroftdp_bnds:	dc.w	$3c01,$43fe
571.1Smycroft		dc.w	$3bcd,$0000
581.1Smycroft
591.1Smycroft	xref	mem_write
601.1Smycroft	xref	bindec
611.1Smycroft	xref	get_fline
621.1Smycroft	xref	round
631.1Smycroft	xref	denorm
641.1Smycroft	xref	dest_ext
651.1Smycroft	xref	dest_dbl
661.1Smycroft	xref	dest_sgl
671.1Smycroft	xref	unf_sub
681.1Smycroft	xref	nrm_set
691.1Smycroft	xref	dnrm_lp
701.1Smycroft	xref	ovf_res
711.1Smycroft	xref	reg_dest
721.1Smycroft	xref	t_ovfl
731.1Smycroft	xref	t_unfl
741.1Smycroft
751.1Smycroft	xdef	res_func
761.1Smycroft	xdef 	p_move
771.1Smycroft
781.1Smycroftres_func:
791.1Smycroft	clr.b	DNRM_FLG(a6)
801.1Smycroft	clr.b	RES_FLG(a6)
811.1Smycroft	clr.b	CU_ONLY(a6)
821.1Smycroft	tst.b	DY_MO_FLG(a6)
831.1Smycroft	beq.b	monadic
841.1Smycroftdyadic:
851.1Smycroft	btst.b	#7,DTAG(a6)	;if dop = norm=000, zero=001,
861.1Smycroft*				;inf=010 or nan=011
871.1Smycroft	beq.b	monadic		;then branch
881.1Smycroft*				;else denorm
891.1Smycroft* HANDLE DESTINATION DENORM HERE
901.1Smycroft*				;set dtag to norm
911.1Smycroft*				;write the tag & fpte15 to the fstack
921.1Smycroft	lea.l	FPTEMP(a6),a0
931.1Smycroft
941.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
951.1Smycroft	sne	LOCAL_SGN(a0)
961.1Smycroft
971.1Smycroft	bsr	nrm_set		;normalize number (exp will go negative)
981.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0) ;get rid of false sign
991.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}	;change back to IEEE ext format
1001.1Smycroft	beq.b	dpos
1011.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
1021.1Smycroftdpos:
1031.1Smycroft	bfclr	DTAG(a6){0:4}	;set tag to normalized, FPTE15 = 0
1041.1Smycroft	bset.b	#4,DTAG(a6)	;set FPTE15
1051.1Smycroft	or.b	#$0f,DNRM_FLG(a6)
1061.1Smycroftmonadic:
1071.1Smycroft	lea.l	ETEMP(a6),a0
1081.1Smycroft	btst.b	#direction_bit,CMDREG1B(a6)	;check direction
1091.1Smycroft	bne.w	opclass3			;it is a mv out
1101.1Smycroft*
1111.1Smycroft* At this point, only oplcass 0 and 2 possible
1121.1Smycroft*
1131.1Smycroft	btst.b	#7,STAG(a6)	;if sop = norm=000, zero=001,
1141.1Smycroft*				;inf=010 or nan=011
1151.1Smycroft	bne.w	mon_dnrm	;else denorm
1161.1Smycroft	tst.b	DY_MO_FLG(a6)	;all cases of dyadic instructions would
1171.1Smycroft	bne.w	normal		;require normalization of denorm
1181.1Smycroft
1191.1Smycroft* At this point:
1201.1Smycroft*	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a
1211.1Smycroft*				fmove = $00  fsmove = $40  fdmove = $44
1221.1Smycroft*				fsqrt = $05* fssqrt = $41  fdsqrt = $45
1231.1Smycroft*				(*fsqrt reencoded to $05)
1241.1Smycroft*
1251.1Smycroft	move.w	CMDREG1B(a6),d0	;get command register
1261.1Smycroft	andi.l	#$7f,d0			;strip to only command word
1271.1Smycroft*
1281.1Smycroft* At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and 
1291.1Smycroft* fdsqrt are possible.
1301.1Smycroft* For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
1311.1Smycroft* For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
1321.1Smycroft*
1331.1Smycroft	btst.l	#0,d0
1341.1Smycroft	bne.w	normal			;weed out fsqrt instructions
1351.1Smycroft*
1361.1Smycroft* cu_norm handles fmove in instructions with normalized inputs.
1371.1Smycroft* The routine round is used to correctly round the input for the
1381.1Smycroft* destination precision and mode.
1391.1Smycroft*
1401.1Smycroftcu_norm:
1411.1Smycroft	st	CU_ONLY(a6)		;set cu-only inst flag
1421.1Smycroft	move.w	CMDREG1B(a6),d0
1431.1Smycroft	andi.b	#$3b,d0		;isolate bits to select inst
1441.1Smycroft	tst.b	d0
1451.1Smycroft	beq.l	cu_nmove	;if zero, it is an fmove
1461.1Smycroft	cmpi.b	#$18,d0
1471.1Smycroft	beq.l	cu_nabs		;if $18, it is fabs
1481.1Smycroft	cmpi.b	#$1a,d0
1491.1Smycroft	beq.l	cu_nneg		;if $1a, it is fneg
1501.1Smycroft*
1511.1Smycroft* Inst is ftst.  Check the source operand and set the cc's accordingly.
1521.1Smycroft* No write is done, so simply rts.
1531.1Smycroft*
1541.1Smycroftcu_ntst:
1551.1Smycroft	move.w	LOCAL_EX(a0),d0
1561.1Smycroft	bclr.l	#15,d0
1571.1Smycroft	sne	LOCAL_SGN(a0)
1581.1Smycroft	beq.b	cu_ntpo
1591.1Smycroft	or.l	#neg_mask,USER_FPSR(a6) ;set N
1601.1Smycroftcu_ntpo:
1611.1Smycroft	cmpi.w	#$7fff,d0	;test for inf/nan
1621.1Smycroft	bne.b	cu_ntcz
1631.1Smycroft	tst.l	LOCAL_HI(a0)
1641.1Smycroft	bne.b	cu_ntn
1651.1Smycroft	tst.l	LOCAL_LO(a0)
1661.1Smycroft	bne.b	cu_ntn
1671.1Smycroft	or.l	#inf_mask,USER_FPSR(a6)
1681.1Smycroft	rts
1691.1Smycroftcu_ntn:
1701.1Smycroft	or.l	#nan_mask,USER_FPSR(a6)
1711.1Smycroft	move.l	ETEMP_EX(a6),FPTEMP_EX(a6)	;set up fptemp sign for 
1721.1Smycroft*						;snan handler
1731.1Smycroft
1741.1Smycroft	rts
1751.1Smycroftcu_ntcz:
1761.1Smycroft	tst.l	LOCAL_HI(a0)
1771.1Smycroft	bne.l	cu_ntsx
1781.1Smycroft	tst.l	LOCAL_LO(a0)
1791.1Smycroft	bne.l	cu_ntsx
1801.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
1811.1Smycroftcu_ntsx:
1821.1Smycroft	rts
1831.1Smycroft*
1841.1Smycroft* Inst is fabs.  Execute the absolute value function on the input.
1851.1Smycroft* Branch to the fmove code.  If the operand is NaN, do nothing.
1861.1Smycroft*
1871.1Smycroftcu_nabs:
1881.1Smycroft	move.b	STAG(a6),d0
1891.1Smycroft	btst.l	#5,d0			;test for NaN or zero
1901.1Smycroft	bne	wr_etemp		;if either, simply write it
1911.1Smycroft	bclr.b	#7,LOCAL_EX(a0)		;do abs
1921.1Smycroft	bra.b	cu_nmove		;fmove code will finish
1931.1Smycroft*
1941.1Smycroft* Inst is fneg.  Execute the negate value function on the input.
1951.1Smycroft* Fall though to the fmove code.  If the operand is NaN, do nothing.
1961.1Smycroft*
1971.1Smycroftcu_nneg:
1981.1Smycroft	move.b	STAG(a6),d0
1991.1Smycroft	btst.l	#5,d0			;test for NaN or zero
2001.1Smycroft	bne	wr_etemp		;if either, simply write it
2011.1Smycroft	bchg.b	#7,LOCAL_EX(a0)		;do neg
2021.1Smycroft*
2031.1Smycroft* Inst is fmove.  This code also handles all result writes.
2041.1Smycroft* If bit 2 is set, round is forced to double.  If it is clear,
2051.1Smycroft* and bit 6 is set, round is forced to single.  If both are clear,
2061.1Smycroft* the round precision is found in the fpcr.  If the rounding precision
2071.1Smycroft* is double or single, round the result before the write.
2081.1Smycroft*
2091.1Smycroftcu_nmove:
2101.1Smycroft	move.b	STAG(a6),d0
2111.1Smycroft	andi.b	#$e0,d0			;isolate stag bits
2121.1Smycroft	bne	wr_etemp		;if not norm, simply write it
2131.1Smycroft	btst.b	#2,CMDREG1B+1(a6)	;check for rd
2141.1Smycroft	bne	cu_nmrd
2151.1Smycroft	btst.b	#6,CMDREG1B+1(a6)	;check for rs
2161.1Smycroft	bne	cu_nmrs
2171.1Smycroft*
2181.1Smycroft* The move or operation is not with forced precision.  Test for
2191.1Smycroft* nan or inf as the input; if so, simply write it to FPn.  Use the
2201.1Smycroft* FPCR_MODE byte to get rounding on norms and zeros.
2211.1Smycroft*
2221.1Smycroftcu_nmnr:
2231.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0
2241.1Smycroft	tst.b	d0			;check for extended
2251.1Smycroft	beq	cu_wrexn		;if so, just write result
2261.1Smycroft	cmpi.b	#1,d0			;check for single
2271.1Smycroft	beq	cu_nmrs			;fall through to double
2281.1Smycroft*
2291.1Smycroft* The move is fdmove or round precision is double.
2301.1Smycroft*
2311.1Smycroftcu_nmrd:
2321.1Smycroft	move.l	#2,d0			;set up the size for denorm
2331.1Smycroft	move.w	LOCAL_EX(a0),d1		;compare exponent to double threshold
2341.1Smycroft	and.w	#$7fff,d1	
2351.1Smycroft	cmp.w	#$3c01,d1
2361.1Smycroft	bls	cu_nunfl
2371.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1	;get rmode
2381.1Smycroft	or.l	#$00020000,d1		;or in rprec (double)
2391.1Smycroft	clr.l	d0			;clear g,r,s for round
2401.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)	;convert to internal format
2411.1Smycroft	sne	LOCAL_SGN(a0)
2421.1Smycroft	bsr.l	round
2431.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}
2441.1Smycroft	beq.b	cu_nmrdc
2451.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
2461.1Smycroftcu_nmrdc:
2471.1Smycroft	move.w	LOCAL_EX(a0),d1		;check for overflow
2481.1Smycroft	and.w	#$7fff,d1
2491.1Smycroft	cmp.w	#$43ff,d1
2501.1Smycroft	bge	cu_novfl		;take care of overflow case
2511.1Smycroft	bra.w	cu_wrexn
2521.1Smycroft*
2531.1Smycroft* The move is fsmove or round precision is single.
2541.1Smycroft*
2551.1Smycroftcu_nmrs:
2561.1Smycroft	move.l	#1,d0
2571.1Smycroft	move.w	LOCAL_EX(a0),d1
2581.1Smycroft	and.w	#$7fff,d1
2591.1Smycroft	cmp.w	#$3f81,d1
2601.1Smycroft	bls	cu_nunfl
2611.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1
2621.1Smycroft	or.l	#$00010000,d1
2631.1Smycroft	clr.l	d0
2641.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
2651.1Smycroft	sne	LOCAL_SGN(a0)
2661.1Smycroft	bsr.l	round
2671.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}
2681.1Smycroft	beq.b	cu_nmrsc
2691.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
2701.1Smycroftcu_nmrsc:
2711.1Smycroft	move.w	LOCAL_EX(a0),d1
2721.1Smycroft	and.w	#$7FFF,d1
2731.1Smycroft	cmp.w	#$407f,d1
2741.1Smycroft	blt	cu_wrexn
2751.1Smycroft*
2761.1Smycroft* The operand is above precision boundaries.  Use t_ovfl to
2771.1Smycroft* generate the correct value.
2781.1Smycroft*
2791.1Smycroftcu_novfl:
2801.1Smycroft	bsr	t_ovfl
2811.1Smycroft	bra	cu_wrexn
2821.1Smycroft*
2831.1Smycroft* The operand is below precision boundaries.  Use denorm to
2841.1Smycroft* generate the correct value.
2851.1Smycroft*
2861.1Smycroftcu_nunfl:
2871.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
2881.1Smycroft	sne	LOCAL_SGN(a0)
2891.1Smycroft	bsr	denorm
2901.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}	;change back to IEEE ext format
2911.1Smycroft	beq.b	cu_nucont
2921.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
2931.1Smycroftcu_nucont:
2941.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1
2951.1Smycroft	btst.b	#2,CMDREG1B+1(a6)	;check for rd
2961.1Smycroft	bne	inst_d
2971.1Smycroft	btst.b	#6,CMDREG1B+1(a6)	;check for rs
2981.1Smycroft	bne	inst_s
2991.1Smycroft	swap	d1
3001.1Smycroft	move.b	FPCR_MODE(a6),d1
3011.1Smycroft	lsr.b	#6,d1
3021.1Smycroft	swap	d1
3031.1Smycroft	bra	inst_sd
3041.1Smycroftinst_d:
3051.1Smycroft	or.l	#$00020000,d1
3061.1Smycroft	bra	inst_sd
3071.1Smycroftinst_s:
3081.1Smycroft	or.l	#$00010000,d1
3091.1Smycroftinst_sd:
3101.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
3111.1Smycroft	sne	LOCAL_SGN(a0)
3121.1Smycroft	bsr.l	round
3131.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}
3141.1Smycroft	beq.b	cu_nuflp
3151.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
3161.1Smycroftcu_nuflp:
3171.1Smycroft	btst.b	#inex2_bit,FPSR_EXCEPT(a6)
3181.1Smycroft	beq.b	cu_nuninx
3191.1Smycroft	or.l	#aunfl_mask,USER_FPSR(a6) ;if the round was inex, set AUNFL
3201.1Smycroftcu_nuninx:
3211.1Smycroft	tst.l	LOCAL_HI(a0)		;test for zero
3221.1Smycroft	bne.b	cu_nunzro
3231.1Smycroft	tst.l	LOCAL_LO(a0)
3241.1Smycroft	bne.b	cu_nunzro
3251.1Smycroft*
3261.1Smycroft* The mantissa is zero from the denorm loop.  Check sign and rmode
3271.1Smycroft* to see if rounding should have occured which would leave the lsb.
3281.1Smycroft*
3291.1Smycroft	move.l	USER_FPCR(a6),d0
3301.1Smycroft	andi.l	#$30,d0		;isolate rmode
3311.1Smycroft	cmpi.l	#$20,d0
3321.1Smycroft	blt.b	cu_nzro
3331.1Smycroft	bne.b	cu_nrp
3341.1Smycroftcu_nrm:
3351.1Smycroft	tst.w	LOCAL_EX(a0)	;if positive, set lsb
3361.1Smycroft	bge.b	cu_nzro
3371.1Smycroft	btst.b	#7,FPCR_MODE(a6) ;check for double
3381.1Smycroft	beq.b	cu_nincs
3391.1Smycroft	bra.b	cu_nincd
3401.1Smycroftcu_nrp:
3411.1Smycroft	tst.w	LOCAL_EX(a0)	;if positive, set lsb
3421.1Smycroft	blt.b	cu_nzro
3431.1Smycroft	btst.b	#7,FPCR_MODE(a6) ;check for double
3441.1Smycroft	beq.b	cu_nincs
3451.1Smycroftcu_nincd:
3461.1Smycroft	or.l	#$800,LOCAL_LO(a0) ;inc for double
3471.1Smycroft	bra	cu_nunzro
3481.1Smycroftcu_nincs:
3491.1Smycroft	or.l	#$100,LOCAL_HI(a0) ;inc for single
3501.1Smycroft	bra	cu_nunzro
3511.1Smycroftcu_nzro:
3521.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
3531.1Smycroft	move.b	STAG(a6),d0
3541.1Smycroft	andi.b	#$e0,d0
3551.1Smycroft	cmpi.b	#$40,d0		;check if input was tagged zero
3561.1Smycroft	beq.b	cu_numv
3571.1Smycroftcu_nunzro:
3581.1Smycroft	or.l	#unfl_mask,USER_FPSR(a6) ;set unfl
3591.1Smycroftcu_numv:
3601.1Smycroft	move.l	(a0),ETEMP(a6)
3611.1Smycroft	move.l	4(a0),ETEMP_HI(a6)
3621.1Smycroft	move.l	8(a0),ETEMP_LO(a6)
3631.1Smycroft*
3641.1Smycroft* Write the result to memory, setting the fpsr cc bits.  NaN and Inf
3651.1Smycroft* bypass cu_wrexn.
3661.1Smycroft*
3671.1Smycroftcu_wrexn:
3681.1Smycroft	tst.w	LOCAL_EX(a0)		;test for zero
3691.1Smycroft	beq.b	cu_wrzero
3701.1Smycroft	cmp.w	#$8000,LOCAL_EX(a0)	;test for zero
3711.1Smycroft	bne.b	cu_wreon
3721.1Smycroftcu_wrzero:
3731.1Smycroft	or.l	#z_mask,USER_FPSR(a6)	;set Z bit
3741.1Smycroftcu_wreon:
3751.1Smycroft	tst.w	LOCAL_EX(a0)
3761.1Smycroft	bpl	wr_etemp
3771.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
3781.1Smycroft	bra	wr_etemp
3791.1Smycroft
3801.1Smycroft*
3811.1Smycroft* HANDLE SOURCE DENORM HERE
3821.1Smycroft*
3831.1Smycroft*				;clear denorm stag to norm
3841.1Smycroft*				;write the new tag & ete15 to the fstack
3851.1Smycroftmon_dnrm:
3861.1Smycroft*
3871.1Smycroft* At this point, check for the cases in which normalizing the 
3881.1Smycroft* denorm produces incorrect results.
3891.1Smycroft*
3901.1Smycroft	tst.b	DY_MO_FLG(a6)	;all cases of dyadic instructions would
3911.1Smycroft	bne.b	nrm_src		;require normalization of denorm
3921.1Smycroft
3931.1Smycroft* At this point:
3941.1Smycroft*	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a
3951.1Smycroft*				fmove = $00  fsmove = $40  fdmove = $44
3961.1Smycroft*				fsqrt = $05* fssqrt = $41  fdsqrt = $45
3971.1Smycroft*				(*fsqrt reencoded to $05)
3981.1Smycroft*
3991.1Smycroft	move.w	CMDREG1B(a6),d0	;get command register
4001.1Smycroft	andi.l	#$7f,d0			;strip to only command word
4011.1Smycroft*
4021.1Smycroft* At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and 
4031.1Smycroft* fdsqrt are possible.
4041.1Smycroft* For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
4051.1Smycroft* For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
4061.1Smycroft*
4071.1Smycroft	btst.l	#0,d0
4081.1Smycroft	bne.b	nrm_src		;weed out fsqrt instructions
4091.1Smycroft	st	CU_ONLY(a6)	;set cu-only inst flag
4101.1Smycroft	bra	cu_dnrm		;fmove, fabs, fneg, ftst 
4111.1Smycroft*				;cases go to cu_dnrm
4121.1Smycroftnrm_src:
4131.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
4141.1Smycroft	sne	LOCAL_SGN(a0)
4151.1Smycroft	bsr	nrm_set		;normalize number (exponent will go 
4161.1Smycroft*				; negative)
4171.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0) ;get rid of false sign
4181.1Smycroft
4191.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}	;change back to IEEE ext format
4201.1Smycroft	beq.b	spos
4211.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0)
4221.1Smycroftspos:
4231.1Smycroft	bfclr	STAG(a6){0:4}	;set tag to normalized, FPTE15 = 0
4241.1Smycroft	bset.b	#4,STAG(a6)	;set ETE15
4251.1Smycroft	or.b	#$f0,DNRM_FLG(a6)
4261.1Smycroftnormal:
4271.1Smycroft	tst.b	DNRM_FLG(a6)	;check if any of the ops were denorms
4281.1Smycroft	bne	ck_wrap		;if so, check if it is a potential
4291.1Smycroft*				;wrap-around case
4301.1Smycroftfix_stk:
4311.1Smycroft	move.b	#$fe,CU_SAVEPC(a6)
4321.1Smycroft	bclr.b	#E1,E_BYTE(a6)
4331.1Smycroft
4341.1Smycroft	clr.w	NMNEXC(a6)
4351.1Smycroft
4361.1Smycroft	st.b	RES_FLG(a6)	;indicate that a restore is needed
4371.1Smycroft	rts
4381.1Smycroft
4391.1Smycroft*
4401.1Smycroft* cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and
4411.1Smycroft* ftst) completly in software without an frestore to the 040. 
4421.1Smycroft*
4431.1Smycroftcu_dnrm:
4441.1Smycroft	st.b	CU_ONLY(a6)
4451.1Smycroft	move.w	CMDREG1B(a6),d0
4461.1Smycroft	andi.b	#$3b,d0		;isolate bits to select inst
4471.1Smycroft	tst.b	d0
4481.1Smycroft	beq.l	cu_dmove	;if zero, it is an fmove
4491.1Smycroft	cmpi.b	#$18,d0
4501.1Smycroft	beq.l	cu_dabs		;if $18, it is fabs
4511.1Smycroft	cmpi.b	#$1a,d0
4521.1Smycroft	beq.l	cu_dneg		;if $1a, it is fneg
4531.1Smycroft*
4541.1Smycroft* Inst is ftst.  Check the source operand and set the cc's accordingly.
4551.1Smycroft* No write is done, so simply rts.
4561.1Smycroft*
4571.1Smycroftcu_dtst:
4581.1Smycroft	move.w	LOCAL_EX(a0),d0
4591.1Smycroft	bclr.l	#15,d0
4601.1Smycroft	sne	LOCAL_SGN(a0)
4611.1Smycroft	beq.b	cu_dtpo
4621.1Smycroft	or.l	#neg_mask,USER_FPSR(a6) ;set N
4631.1Smycroftcu_dtpo:
4641.1Smycroft	cmpi.w	#$7fff,d0	;test for inf/nan
4651.1Smycroft	bne.b	cu_dtcz
4661.1Smycroft	tst.l	LOCAL_HI(a0)
4671.1Smycroft	bne.b	cu_dtn
4681.1Smycroft	tst.l	LOCAL_LO(a0)
4691.1Smycroft	bne.b	cu_dtn
4701.1Smycroft	or.l	#inf_mask,USER_FPSR(a6)
4711.1Smycroft	rts
4721.1Smycroftcu_dtn:
4731.1Smycroft	or.l	#nan_mask,USER_FPSR(a6)
4741.1Smycroft	move.l	ETEMP_EX(a6),FPTEMP_EX(a6)	;set up fptemp sign for 
4751.1Smycroft*						;snan handler
4761.1Smycroft	rts
4771.1Smycroftcu_dtcz:
4781.1Smycroft	tst.l	LOCAL_HI(a0)
4791.1Smycroft	bne.l	cu_dtsx
4801.1Smycroft	tst.l	LOCAL_LO(a0)
4811.1Smycroft	bne.l	cu_dtsx
4821.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
4831.1Smycroftcu_dtsx:
4841.1Smycroft	rts
4851.1Smycroft*
4861.1Smycroft* Inst is fabs.  Execute the absolute value function on the input.
4871.1Smycroft* Branch to the fmove code.
4881.1Smycroft*
4891.1Smycroftcu_dabs:
4901.1Smycroft	bclr.b	#7,LOCAL_EX(a0)		;do abs
4911.1Smycroft	bra.b	cu_dmove		;fmove code will finish
4921.1Smycroft*
4931.1Smycroft* Inst is fneg.  Execute the negate value function on the input.
4941.1Smycroft* Fall though to the fmove code.
4951.1Smycroft*
4961.1Smycroftcu_dneg:
4971.1Smycroft	bchg.b	#7,LOCAL_EX(a0)		;do neg
4981.1Smycroft*
4991.1Smycroft* Inst is fmove.  This code also handles all result writes.
5001.1Smycroft* If bit 2 is set, round is forced to double.  If it is clear,
5011.1Smycroft* and bit 6 is set, round is forced to single.  If both are clear,
5021.1Smycroft* the round precision is found in the fpcr.  If the rounding precision
5031.1Smycroft* is double or single, the result is zero, and the mode is checked
5041.1Smycroft* to determine if the lsb of the result should be set.
5051.1Smycroft*
5061.1Smycroftcu_dmove:
5071.1Smycroft	btst.b	#2,CMDREG1B+1(a6)	;check for rd
5081.1Smycroft	bne	cu_dmrd
5091.1Smycroft	btst.b	#6,CMDREG1B+1(a6)	;check for rs
5101.1Smycroft	bne	cu_dmrs
5111.1Smycroft*
5121.1Smycroft* The move or operation is not with forced precision.  Use the
5131.1Smycroft* FPCR_MODE byte to get rounding.
5141.1Smycroft*
5151.1Smycroftcu_dmnr:
5161.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0
5171.1Smycroft	tst.b	d0			;check for extended
5181.1Smycroft	beq	cu_wrexd		;if so, just write result
5191.1Smycroft	cmpi.b	#1,d0			;check for single
5201.1Smycroft	beq	cu_dmrs			;fall through to double
5211.1Smycroft*
5221.1Smycroft* The move is fdmove or round precision is double.  Result is zero.
5231.1Smycroft* Check rmode for rp or rm and set lsb accordingly.
5241.1Smycroft*
5251.1Smycroftcu_dmrd:
5261.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1	;get rmode
5271.1Smycroft	tst.w	LOCAL_EX(a0)		;check sign
5281.1Smycroft	blt.b	cu_dmdn
5291.1Smycroft	cmpi.b	#3,d1			;check for rp
5301.1Smycroft	bne	cu_dpd			;load double pos zero
5311.1Smycroft	bra	cu_dpdr			;load double pos zero w/lsb
5321.1Smycroftcu_dmdn:
5331.1Smycroft	cmpi.b	#2,d1			;check for rm
5341.1Smycroft	bne	cu_dnd			;load double neg zero
5351.1Smycroft	bra	cu_dndr			;load double neg zero w/lsb
5361.1Smycroft*
5371.1Smycroft* The move is fsmove or round precision is single.  Result is zero.
5381.1Smycroft* Check for rp or rm and set lsb accordingly.
5391.1Smycroft*
5401.1Smycroftcu_dmrs:
5411.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1	;get rmode
5421.1Smycroft	tst.w	LOCAL_EX(a0)		;check sign
5431.1Smycroft	blt.b	cu_dmsn
5441.1Smycroft	cmpi.b	#3,d1			;check for rp
5451.1Smycroft	bne	cu_spd			;load single pos zero
5461.1Smycroft	bra	cu_spdr			;load single pos zero w/lsb
5471.1Smycroftcu_dmsn:
5481.1Smycroft	cmpi.b	#2,d1			;check for rm
5491.1Smycroft	bne	cu_snd			;load single neg zero
5501.1Smycroft	bra	cu_sndr			;load single neg zero w/lsb
5511.1Smycroft*
5521.1Smycroft* The precision is extended, so the result in etemp is correct.
5531.1Smycroft* Simply set unfl (not inex2 or aunfl) and write the result to 
5541.1Smycroft* the correct fp register.
5551.1Smycroftcu_wrexd:
5561.1Smycroft	or.l	#unfl_mask,USER_FPSR(a6)
5571.1Smycroft	tst.w	LOCAL_EX(a0)
5581.1Smycroft	beq	wr_etemp
5591.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
5601.1Smycroft	bra	wr_etemp
5611.1Smycroft*
5621.1Smycroft* These routines write +/- zero in double format.  The routines
5631.1Smycroft* cu_dpdr and cu_dndr set the double lsb.
5641.1Smycroft*
5651.1Smycroftcu_dpd:
5661.1Smycroft	move.l	#$3c010000,LOCAL_EX(a0)	;force pos double zero
5671.1Smycroft	clr.l	LOCAL_HI(a0)
5681.1Smycroft	clr.l	LOCAL_LO(a0)
5691.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
5701.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
5711.1Smycroft	bra	wr_etemp
5721.1Smycroftcu_dpdr:
5731.1Smycroft	move.l	#$3c010000,LOCAL_EX(a0)	;force pos double zero
5741.1Smycroft	clr.l	LOCAL_HI(a0)
5751.1Smycroft	move.l	#$800,LOCAL_LO(a0)	;with lsb set
5761.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
5771.1Smycroft	bra	wr_etemp
5781.1Smycroftcu_dnd:
5791.1Smycroft	move.l	#$bc010000,LOCAL_EX(a0)	;force pos double zero
5801.1Smycroft	clr.l	LOCAL_HI(a0)
5811.1Smycroft	clr.l	LOCAL_LO(a0)
5821.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
5831.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
5841.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
5851.1Smycroft	bra	wr_etemp
5861.1Smycroftcu_dndr:
5871.1Smycroft	move.l	#$bc010000,LOCAL_EX(a0)	;force pos double zero
5881.1Smycroft	clr.l	LOCAL_HI(a0)
5891.1Smycroft	move.l	#$800,LOCAL_LO(a0)	;with lsb set
5901.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
5911.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
5921.1Smycroft	bra	wr_etemp
5931.1Smycroft*
5941.1Smycroft* These routines write +/- zero in single format.  The routines
5951.1Smycroft* cu_dpdr and cu_dndr set the single lsb.
5961.1Smycroft*
5971.1Smycroftcu_spd:
5981.1Smycroft	move.l	#$3f810000,LOCAL_EX(a0)	;force pos single zero
5991.1Smycroft	clr.l	LOCAL_HI(a0)
6001.1Smycroft	clr.l	LOCAL_LO(a0)
6011.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
6021.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
6031.1Smycroft	bra	wr_etemp
6041.1Smycroftcu_spdr:
6051.1Smycroft	move.l	#$3f810000,LOCAL_EX(a0)	;force pos single zero
6061.1Smycroft	move.l	#$100,LOCAL_HI(a0)	;with lsb set
6071.1Smycroft	clr.l	LOCAL_LO(a0)
6081.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
6091.1Smycroft	bra	wr_etemp
6101.1Smycroftcu_snd:
6111.1Smycroft	move.l	#$bf810000,LOCAL_EX(a0)	;force pos single zero
6121.1Smycroft	clr.l	LOCAL_HI(a0)
6131.1Smycroft	clr.l	LOCAL_LO(a0)
6141.1Smycroft	or.l	#z_mask,USER_FPSR(a6)
6151.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
6161.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
6171.1Smycroft	bra	wr_etemp
6181.1Smycroftcu_sndr:
6191.1Smycroft	move.l	#$bf810000,LOCAL_EX(a0)	;force pos single zero
6201.1Smycroft	move.l	#$100,LOCAL_HI(a0)	;with lsb set
6211.1Smycroft	clr.l	LOCAL_LO(a0)
6221.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
6231.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
6241.1Smycroft	bra	wr_etemp
6251.1Smycroft	
6261.1Smycroft*
6271.1Smycroft* This code checks for 16-bit overflow conditions on dyadic
6281.1Smycroft* operations which are not restorable into the floating-point
6291.1Smycroft* unit and must be completed in software.  Basically, this
6301.1Smycroft* condition exists with a very large norm and a denorm.  One
6311.1Smycroft* of the operands must be denormalized to enter this code.
6321.1Smycroft*
6331.1Smycroft* Flags used:
6341.1Smycroft*	DY_MO_FLG contains 0 for monadic op, $ff for dyadic
6351.1Smycroft*	DNRM_FLG contains $00 for neither op denormalized
6361.1Smycroft*	                  $0f for the destination op denormalized
6371.1Smycroft*	                  $f0 for the source op denormalized
6381.1Smycroft*	                  $ff for both ops denormalzed
6391.1Smycroft*
6401.1Smycroft* The wrap-around condition occurs for add, sub, div, and cmp
6411.1Smycroft* when 
6421.1Smycroft*
6431.1Smycroft*	abs(dest_exp - src_exp) >= $8000
6441.1Smycroft*
6451.1Smycroft* and for mul when
6461.1Smycroft*
6471.1Smycroft*	(dest_exp + src_exp) < $0
6481.1Smycroft*
6491.1Smycroft* we must process the operation here if this case is true.
6501.1Smycroft*
6511.1Smycroft* The rts following the frcfpn routine is the exit from res_func
6521.1Smycroft* for this condition.  The restore flag (RES_FLG) is left clear.
6531.1Smycroft* No frestore is done unless an exception is to be reported.
6541.1Smycroft*
6551.1Smycroft* For fadd: 
6561.1Smycroft*	if(sign_of(dest) != sign_of(src))
6571.1Smycroft*		replace exponent of src with $3fff (keep sign)
6581.1Smycroft*		use fpu to perform dest+new_src (user's rmode and X)
6591.1Smycroft*		clr sticky
6601.1Smycroft*	else
6611.1Smycroft*		set sticky
6621.1Smycroft*	call round with user's precision and mode
6631.1Smycroft*	move result to fpn and wbtemp
6641.1Smycroft*
6651.1Smycroft* For fsub:
6661.1Smycroft*	if(sign_of(dest) == sign_of(src))
6671.1Smycroft*		replace exponent of src with $3fff (keep sign)
6681.1Smycroft*		use fpu to perform dest+new_src (user's rmode and X)
6691.1Smycroft*		clr sticky
6701.1Smycroft*	else
6711.1Smycroft*		set sticky
6721.1Smycroft*	call round with user's precision and mode
6731.1Smycroft*	move result to fpn and wbtemp
6741.1Smycroft*
6751.1Smycroft* For fdiv/fsgldiv:
6761.1Smycroft*	if(both operands are denorm)
6771.1Smycroft*		restore_to_fpu;
6781.1Smycroft*	if(dest is norm)
6791.1Smycroft*		force_ovf;
6801.1Smycroft*	else(dest is denorm)
6811.1Smycroft*		force_unf:
6821.1Smycroft*
6831.1Smycroft* For fcmp:
6841.1Smycroft*	if(dest is norm)
6851.1Smycroft*		N = sign_of(dest);
6861.1Smycroft*	else(dest is denorm)
6871.1Smycroft*		N = sign_of(src);
6881.1Smycroft*
6891.1Smycroft* For fmul:
6901.1Smycroft*	if(both operands are denorm)
6911.1Smycroft*		force_unf;
6921.1Smycroft*	if((dest_exp + src_exp) < 0)
6931.1Smycroft*		force_unf:
6941.1Smycroft*	else
6951.1Smycroft*		restore_to_fpu;
6961.1Smycroft*
6971.1Smycroft* local equates:
6981.1Smycroftaddcode	equ	$22
6991.1Smycroftsubcode	equ	$28
7001.1Smycroftmulcode	equ	$23
7011.1Smycroftdivcode	equ	$20
7021.1Smycroftcmpcode	equ	$38
7031.1Smycroftck_wrap:
7041.1Smycroft	tst.b	DY_MO_FLG(a6)	;check for fsqrt
7051.1Smycroft	beq	fix_stk		;if zero, it is fsqrt
7061.1Smycroft	move.w	CMDREG1B(a6),d0
7071.1Smycroft	andi.w	#$3b,d0		;strip to command bits
7081.1Smycroft	cmpi.w	#addcode,d0
7091.1Smycroft	beq	wrap_add
7101.1Smycroft	cmpi.w	#subcode,d0
7111.1Smycroft	beq	wrap_sub
7121.1Smycroft	cmpi.w	#mulcode,d0
7131.1Smycroft	beq	wrap_mul
7141.1Smycroft	cmpi.w	#cmpcode,d0
7151.1Smycroft	beq	wrap_cmp
7161.1Smycroft*
7171.1Smycroft* Inst is fdiv.  
7181.1Smycroft*
7191.1Smycroftwrap_div:
7201.1Smycroft	cmp.b	#$ff,DNRM_FLG(a6) ;if both ops denorm, 
7211.1Smycroft	beq	fix_stk		 ;restore to fpu
7221.1Smycroft*
7231.1Smycroft* One of the ops is denormalized.  Test for wrap condition
7241.1Smycroft* and force the result.
7251.1Smycroft*
7261.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;check for dest denorm
7271.1Smycroft	bne.b	div_srcd
7281.1Smycroftdiv_destd:
7291.1Smycroft	bsr.l	ckinf_ns
7301.1Smycroft	bne	fix_stk
7311.1Smycroft	bfextu	ETEMP_EX(a6){1:15},d0	;get src exp (always pos)
7321.1Smycroft	bfexts	FPTEMP_EX(a6){1:15},d1	;get dest exp (always neg)
7331.1Smycroft	sub.l	d1,d0			;subtract dest from src
7341.1Smycroft	cmp.l	#$7fff,d0
7351.1Smycroft	blt	fix_stk			;if less, not wrap case
7361.1Smycroft	clr.b	WBTEMP_SGN(a6)
7371.1Smycroft	move.w	ETEMP_EX(a6),d0		;find the sign of the result
7381.1Smycroft	move.w	FPTEMP_EX(a6),d1
7391.1Smycroft	eor.w	d1,d0
7401.1Smycroft	andi.w	#$8000,d0
7411.1Smycroft	beq	force_unf
7421.1Smycroft	st.b	WBTEMP_SGN(a6)
7431.1Smycroft	bra	force_unf
7441.1Smycroft
7451.1Smycroftckinf_ns:
7461.1Smycroft	move.b	STAG(a6),d0		;check source tag for inf or nan
7471.1Smycroft	bra	ck_in_com
7481.1Smycroftckinf_nd:
7491.1Smycroft	move.b	DTAG(a6),d0		;check destination tag for inf or nan
7501.1Smycroftck_in_com:	
7511.1Smycroft	andi.b	#$60,d0			;isolate tag bits
7521.1Smycroft	cmp.b	#$40,d0			;is it inf?
7531.1Smycroft	beq	nan_or_inf		;not wrap case
7541.1Smycroft	cmp.b	#$60,d0			;is it nan?
7551.1Smycroft	beq	nan_or_inf		;yes, not wrap case?
7561.1Smycroft	cmp.b	#$20,d0			;is it a zero?
7571.1Smycroft	beq	nan_or_inf		;yes
7581.1Smycroft	clr.l	d0
7591.1Smycroft	rts				;then it is either a zero of norm,
7601.1Smycroft*					;check wrap case
7611.1Smycroftnan_or_inf:
7621.1Smycroft	moveq.l	#-1,d0
7631.1Smycroft	rts
7641.1Smycroft
7651.1Smycroft
7661.1Smycroft
7671.1Smycroftdiv_srcd:
7681.1Smycroft	bsr.l	ckinf_nd
7691.1Smycroft	bne	fix_stk
7701.1Smycroft	bfextu	FPTEMP_EX(a6){1:15},d0	;get dest exp (always pos)
7711.1Smycroft	bfexts	ETEMP_EX(a6){1:15},d1	;get src exp (always neg)
7721.1Smycroft	sub.l	d1,d0			;subtract src from dest
7731.1Smycroft	cmp.l	#$8000,d0
7741.1Smycroft	blt	fix_stk			;if less, not wrap case
7751.1Smycroft	clr.b	WBTEMP_SGN(a6)
7761.1Smycroft	move.w	ETEMP_EX(a6),d0		;find the sign of the result
7771.1Smycroft	move.w	FPTEMP_EX(a6),d1
7781.1Smycroft	eor.w	d1,d0
7791.1Smycroft	andi.w	#$8000,d0
7801.1Smycroft	beq.b	force_ovf
7811.1Smycroft	st.b	WBTEMP_SGN(a6)
7821.1Smycroft*
7831.1Smycroft* This code handles the case of the instruction resulting in 
7841.1Smycroft* an overflow condition.
7851.1Smycroft*
7861.1Smycroftforce_ovf:
7871.1Smycroft	bclr.b	#E1,E_BYTE(a6)
7881.1Smycroft	or.l	#ovfl_inx_mask,USER_FPSR(a6)
7891.1Smycroft	clr.w	NMNEXC(a6)
7901.1Smycroft	lea.l	WBTEMP(a6),a0		;point a0 to memory location
7911.1Smycroft	move.w	CMDREG1B(a6),d0
7921.1Smycroft	btst.l	#6,d0			;test for forced precision
7931.1Smycroft	beq.b	frcovf_fpcr
7941.1Smycroft	btst.l	#2,d0			;check for double
7951.1Smycroft	bne.b	frcovf_dbl
7961.1Smycroft	move.l	#$1,d0			;inst is forced single
7971.1Smycroft	bra.b	frcovf_rnd
7981.1Smycroftfrcovf_dbl:
7991.1Smycroft	move.l	#$2,d0			;inst is forced double
8001.1Smycroft	bra.b	frcovf_rnd
8011.1Smycroftfrcovf_fpcr:
8021.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0	;inst not forced - use fpcr prec
8031.1Smycroftfrcovf_rnd:
8041.1Smycroft
8051.1Smycroft* The 881/882 does not set inex2 for the following case, so the 
8061.1Smycroft* line is commented out to be compatible with 881/882
8071.1Smycroft*	tst.b	d0
8081.1Smycroft*	beq.b	frcovf_x
8091.1Smycroft*	or.l	#inex2_mask,USER_FPSR(a6) ;if prec is s or d, set inex2
8101.1Smycroft
8111.1Smycroft*frcovf_x:
8121.1Smycroft	bsr.l	ovf_res			;get correct result based on
8131.1Smycroft*					;round precision/mode.  This 
8141.1Smycroft*					;sets FPSR_CC correctly
8151.1Smycroft*					;returns in external format
8161.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}
8171.1Smycroft	beq	frcfpn
8181.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
8191.1Smycroft	bra	frcfpn
8201.1Smycroft*
8211.1Smycroft* Inst is fadd.
8221.1Smycroft*
8231.1Smycroftwrap_add:
8241.1Smycroft	cmp.b	#$ff,DNRM_FLG(a6) ;if both ops denorm, 
8251.1Smycroft	beq	fix_stk		 ;restore to fpu
8261.1Smycroft*
8271.1Smycroft* One of the ops is denormalized.  Test for wrap condition
8281.1Smycroft* and complete the instruction.
8291.1Smycroft*
8301.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;check for dest denorm
8311.1Smycroft	bne.b	add_srcd
8321.1Smycroftadd_destd:
8331.1Smycroft	bsr.l	ckinf_ns
8341.1Smycroft	bne	fix_stk
8351.1Smycroft	bfextu	ETEMP_EX(a6){1:15},d0	;get src exp (always pos)
8361.1Smycroft	bfexts	FPTEMP_EX(a6){1:15},d1	;get dest exp (always neg)
8371.1Smycroft	sub.l	d1,d0			;subtract dest from src
8381.1Smycroft	cmp.l	#$8000,d0
8391.1Smycroft	blt	fix_stk			;if less, not wrap case
8401.1Smycroft	bra	add_wrap
8411.1Smycroftadd_srcd:
8421.1Smycroft	bsr.l	ckinf_nd
8431.1Smycroft	bne	fix_stk
8441.1Smycroft	bfextu	FPTEMP_EX(a6){1:15},d0	;get dest exp (always pos)
8451.1Smycroft	bfexts	ETEMP_EX(a6){1:15},d1	;get src exp (always neg)
8461.1Smycroft	sub.l	d1,d0			;subtract src from dest
8471.1Smycroft	cmp.l	#$8000,d0
8481.1Smycroft	blt	fix_stk			;if less, not wrap case
8491.1Smycroft*
8501.1Smycroft* Check the signs of the operands.  If they are unlike, the fpu
8511.1Smycroft* can be used to add the norm and 1.0 with the sign of the
8521.1Smycroft* denorm and it will correctly generate the result in extended
8531.1Smycroft* precision.  We can then call round with no sticky and the result
8541.1Smycroft* will be correct for the user's rounding mode and precision.  If
8551.1Smycroft* the signs are the same, we call round with the sticky bit set
8561.1Smycroft* and the result will be correctfor the user's rounding mode and
8571.1Smycroft* precision.
8581.1Smycroft*
8591.1Smycroftadd_wrap:
8601.1Smycroft	move.w	ETEMP_EX(a6),d0
8611.1Smycroft	move.w	FPTEMP_EX(a6),d1
8621.1Smycroft	eor.w	d1,d0
8631.1Smycroft	andi.w	#$8000,d0
8641.1Smycroft	beq	add_same
8651.1Smycroft*
8661.1Smycroft* The signs are unlike.
8671.1Smycroft*
8681.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;is dest the denorm?
8691.1Smycroft	bne.b	add_u_srcd
8701.1Smycroft	move.w	FPTEMP_EX(a6),d0
8711.1Smycroft	andi.w	#$8000,d0
8721.1Smycroft	or.w	#$3fff,d0	;force the exponent to +/- 1
8731.1Smycroft	move.w	d0,FPTEMP_EX(a6) ;in the denorm
8741.1Smycroft	move.l	USER_FPCR(a6),d0
8751.1Smycroft	andi.l	#$30,d0
8761.1Smycroft	fmove.l	d0,fpcr		;set up users rmode and X
8771.1Smycroft	fmove.x	ETEMP(a6),fp0
8781.1Smycroft	fadd.x	FPTEMP(a6),fp0
8791.1Smycroft	lea.l	WBTEMP(a6),a0	;point a0 to wbtemp in frame
8801.1Smycroft	fmove.l	fpsr,d1
8811.1Smycroft	or.l	d1,USER_FPSR(a6) ;capture cc's and inex from fadd
8821.1Smycroft	fmove.x	fp0,WBTEMP(a6)	;write result to memory
8831.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
8841.1Smycroft	move.l	USER_FPCR(a6),d1
8851.1Smycroft	andi.l	#$c0,d1
8861.1Smycroft	lsr.l	#6,d1		;put precision in upper word
8871.1Smycroft	swap	d1
8881.1Smycroft	or.l	d0,d1		;set up for round call
8891.1Smycroft	clr.l	d0		;force sticky to zero
8901.1Smycroft	bclr.b	#sign_bit,WBTEMP_EX(a6)
8911.1Smycroft	sne	WBTEMP_SGN(a6)
8921.1Smycroft	bsr.l	round		;round result to users rmode & prec
8931.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
8941.1Smycroft	beq	frcfpnr
8951.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
8961.1Smycroft	bra	frcfpnr
8971.1Smycroftadd_u_srcd:
8981.1Smycroft	move.w	ETEMP_EX(a6),d0
8991.1Smycroft	andi.w	#$8000,d0
9001.1Smycroft	or.w	#$3fff,d0	;force the exponent to +/- 1
9011.1Smycroft	move.w	d0,ETEMP_EX(a6) ;in the denorm
9021.1Smycroft	move.l	USER_FPCR(a6),d0
9031.1Smycroft	andi.l	#$30,d0
9041.1Smycroft	fmove.l	d0,fpcr		;set up users rmode and X
9051.1Smycroft	fmove.x	ETEMP(a6),fp0
9061.1Smycroft	fadd.x	FPTEMP(a6),fp0
9071.1Smycroft	fmove.l	fpsr,d1
9081.1Smycroft	or.l	d1,USER_FPSR(a6) ;capture cc's and inex from fadd
9091.1Smycroft	lea.l	WBTEMP(a6),a0	;point a0 to wbtemp in frame
9101.1Smycroft	fmove.x	fp0,WBTEMP(a6)	;write result to memory
9111.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
9121.1Smycroft	move.l	USER_FPCR(a6),d1
9131.1Smycroft	andi.l	#$c0,d1
9141.1Smycroft	lsr.l	#6,d1		;put precision in upper word
9151.1Smycroft	swap	d1
9161.1Smycroft	or.l	d0,d1		;set up for round call
9171.1Smycroft	clr.l	d0		;force sticky to zero
9181.1Smycroft	bclr.b	#sign_bit,WBTEMP_EX(a6)
9191.1Smycroft	sne	WBTEMP_SGN(a6)	;use internal format for round
9201.1Smycroft	bsr.l	round		;round result to users rmode & prec
9211.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
9221.1Smycroft	beq	frcfpnr
9231.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
9241.1Smycroft	bra	frcfpnr
9251.1Smycroft*
9261.1Smycroft* Signs are alike:
9271.1Smycroft*
9281.1Smycroftadd_same:
9291.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;is dest the denorm?
9301.1Smycroft	bne.b	add_s_srcd
9311.1Smycroftadd_s_destd:
9321.1Smycroft	lea.l	ETEMP(a6),a0
9331.1Smycroft	move.l	USER_FPCR(a6),d0
9341.1Smycroft	andi.l	#$30,d0
9351.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
9361.1Smycroft	move.l	USER_FPCR(a6),d1
9371.1Smycroft	andi.l	#$c0,d1
9381.1Smycroft	lsr.l	#6,d1		;put precision in upper word
9391.1Smycroft	swap	d1
9401.1Smycroft	or.l	d0,d1		;set up for round call
9411.1Smycroft	move.l	#$20000000,d0	;set sticky for round
9421.1Smycroft	bclr.b	#sign_bit,ETEMP_EX(a6)
9431.1Smycroft	sne	ETEMP_SGN(a6)
9441.1Smycroft	bsr.l	round		;round result to users rmode & prec
9451.1Smycroft	bfclr	ETEMP_SGN(a6){0:8}	;convert back to IEEE ext format
9461.1Smycroft	beq.b	add_s_dclr
9471.1Smycroft	bset.b	#sign_bit,ETEMP_EX(a6)
9481.1Smycroftadd_s_dclr:
9491.1Smycroft	lea.l	WBTEMP(a6),a0
9501.1Smycroft	move.l	ETEMP(a6),(a0)	;write result to wbtemp
9511.1Smycroft	move.l	ETEMP_HI(a6),4(a0)
9521.1Smycroft	move.l	ETEMP_LO(a6),8(a0)
9531.1Smycroft	tst.w	ETEMP_EX(a6)
9541.1Smycroft	bgt	add_ckovf
9551.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
9561.1Smycroft	bra	add_ckovf
9571.1Smycroftadd_s_srcd:
9581.1Smycroft	lea.l	FPTEMP(a6),a0
9591.1Smycroft	move.l	USER_FPCR(a6),d0
9601.1Smycroft	andi.l	#$30,d0
9611.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
9621.1Smycroft	move.l	USER_FPCR(a6),d1
9631.1Smycroft	andi.l	#$c0,d1
9641.1Smycroft	lsr.l	#6,d1		;put precision in upper word
9651.1Smycroft	swap	d1
9661.1Smycroft	or.l	d0,d1		;set up for round call
9671.1Smycroft	move.l	#$20000000,d0	;set sticky for round
9681.1Smycroft	bclr.b	#sign_bit,FPTEMP_EX(a6)
9691.1Smycroft	sne	FPTEMP_SGN(a6)
9701.1Smycroft	bsr.l	round		;round result to users rmode & prec
9711.1Smycroft	bfclr	FPTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
9721.1Smycroft	beq.b	add_s_sclr
9731.1Smycroft	bset.b	#sign_bit,FPTEMP_EX(a6)
9741.1Smycroftadd_s_sclr:
9751.1Smycroft	lea.l	WBTEMP(a6),a0
9761.1Smycroft	move.l	FPTEMP(a6),(a0)	;write result to wbtemp
9771.1Smycroft	move.l	FPTEMP_HI(a6),4(a0)
9781.1Smycroft	move.l	FPTEMP_LO(a6),8(a0)
9791.1Smycroft	tst.w	FPTEMP_EX(a6)
9801.1Smycroft	bgt	add_ckovf
9811.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
9821.1Smycroftadd_ckovf:
9831.1Smycroft	move.w	WBTEMP_EX(a6),d0
9841.1Smycroft	andi.w	#$7fff,d0
9851.1Smycroft	cmpi.w	#$7fff,d0
9861.1Smycroft	bne	frcfpnr
9871.1Smycroft*
9881.1Smycroft* The result has overflowed to $7fff exponent.  Set I, ovfl,
9891.1Smycroft* and aovfl, and clr the mantissa (incorrectly set by the
9901.1Smycroft* round routine.)
9911.1Smycroft*
9921.1Smycroft	or.l	#inf_mask+ovfl_inx_mask,USER_FPSR(a6)	
9931.1Smycroft	clr.l	4(a0)
9941.1Smycroft	bra	frcfpnr
9951.1Smycroft*
9961.1Smycroft* Inst is fsub.
9971.1Smycroft*
9981.1Smycroftwrap_sub:
9991.1Smycroft	cmp.b	#$ff,DNRM_FLG(a6) ;if both ops denorm, 
10001.1Smycroft	beq	fix_stk		 ;restore to fpu
10011.1Smycroft*
10021.1Smycroft* One of the ops is denormalized.  Test for wrap condition
10031.1Smycroft* and complete the instruction.
10041.1Smycroft*
10051.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;check for dest denorm
10061.1Smycroft	bne.b	sub_srcd
10071.1Smycroftsub_destd:
10081.1Smycroft	bsr.l	ckinf_ns
10091.1Smycroft	bne	fix_stk
10101.1Smycroft	bfextu	ETEMP_EX(a6){1:15},d0	;get src exp (always pos)
10111.1Smycroft	bfexts	FPTEMP_EX(a6){1:15},d1	;get dest exp (always neg)
10121.1Smycroft	sub.l	d1,d0			;subtract src from dest
10131.1Smycroft	cmp.l	#$8000,d0
10141.1Smycroft	blt	fix_stk			;if less, not wrap case
10151.1Smycroft	bra	sub_wrap
10161.1Smycroftsub_srcd:
10171.1Smycroft	bsr.l	ckinf_nd
10181.1Smycroft	bne	fix_stk
10191.1Smycroft	bfextu	FPTEMP_EX(a6){1:15},d0	;get dest exp (always pos)
10201.1Smycroft	bfexts	ETEMP_EX(a6){1:15},d1	;get src exp (always neg)
10211.1Smycroft	sub.l	d1,d0			;subtract dest from src
10221.1Smycroft	cmp.l	#$8000,d0
10231.1Smycroft	blt	fix_stk			;if less, not wrap case
10241.1Smycroft*
10251.1Smycroft* Check the signs of the operands.  If they are alike, the fpu
10261.1Smycroft* can be used to subtract from the norm 1.0 with the sign of the
10271.1Smycroft* denorm and it will correctly generate the result in extended
10281.1Smycroft* precision.  We can then call round with no sticky and the result
10291.1Smycroft* will be correct for the user's rounding mode and precision.  If
10301.1Smycroft* the signs are unlike, we call round with the sticky bit set
10311.1Smycroft* and the result will be correctfor the user's rounding mode and
10321.1Smycroft* precision.
10331.1Smycroft*
10341.1Smycroftsub_wrap:
10351.1Smycroft	move.w	ETEMP_EX(a6),d0
10361.1Smycroft	move.w	FPTEMP_EX(a6),d1
10371.1Smycroft	eor.w	d1,d0
10381.1Smycroft	andi.w	#$8000,d0
10391.1Smycroft	bne	sub_diff
10401.1Smycroft*
10411.1Smycroft* The signs are alike.
10421.1Smycroft*
10431.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;is dest the denorm?
10441.1Smycroft	bne.b	sub_u_srcd
10451.1Smycroft	move.w	FPTEMP_EX(a6),d0
10461.1Smycroft	andi.w	#$8000,d0
10471.1Smycroft	or.w	#$3fff,d0	;force the exponent to +/- 1
10481.1Smycroft	move.w	d0,FPTEMP_EX(a6) ;in the denorm
10491.1Smycroft	move.l	USER_FPCR(a6),d0
10501.1Smycroft	andi.l	#$30,d0
10511.1Smycroft	fmove.l	d0,fpcr		;set up users rmode and X
10521.1Smycroft	fmove.x	FPTEMP(a6),fp0
10531.1Smycroft	fsub.x	ETEMP(a6),fp0
10541.1Smycroft	fmove.l	fpsr,d1
10551.1Smycroft	or.l	d1,USER_FPSR(a6) ;capture cc's and inex from fadd
10561.1Smycroft	lea.l	WBTEMP(a6),a0	;point a0 to wbtemp in frame
10571.1Smycroft	fmove.x	fp0,WBTEMP(a6)	;write result to memory
10581.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
10591.1Smycroft	move.l	USER_FPCR(a6),d1
10601.1Smycroft	andi.l	#$c0,d1
10611.1Smycroft	lsr.l	#6,d1		;put precision in upper word
10621.1Smycroft	swap	d1
10631.1Smycroft	or.l	d0,d1		;set up for round call
10641.1Smycroft	clr.l	d0		;force sticky to zero
10651.1Smycroft	bclr.b	#sign_bit,WBTEMP_EX(a6)
10661.1Smycroft	sne	WBTEMP_SGN(a6)
10671.1Smycroft	bsr.l	round		;round result to users rmode & prec
10681.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
10691.1Smycroft	beq	frcfpnr
10701.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
10711.1Smycroft	bra	frcfpnr
10721.1Smycroftsub_u_srcd:
10731.1Smycroft	move.w	ETEMP_EX(a6),d0
10741.1Smycroft	andi.w	#$8000,d0
10751.1Smycroft	or.w	#$3fff,d0	;force the exponent to +/- 1
10761.1Smycroft	move.w	d0,ETEMP_EX(a6) ;in the denorm
10771.1Smycroft	move.l	USER_FPCR(a6),d0
10781.1Smycroft	andi.l	#$30,d0
10791.1Smycroft	fmove.l	d0,fpcr		;set up users rmode and X
10801.1Smycroft	fmove.x	FPTEMP(a6),fp0
10811.1Smycroft	fsub.x	ETEMP(a6),fp0
10821.1Smycroft	fmove.l	fpsr,d1
10831.1Smycroft	or.l	d1,USER_FPSR(a6) ;capture cc's and inex from fadd
10841.1Smycroft	lea.l	WBTEMP(a6),a0	;point a0 to wbtemp in frame
10851.1Smycroft	fmove.x	fp0,WBTEMP(a6)	;write result to memory
10861.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
10871.1Smycroft	move.l	USER_FPCR(a6),d1
10881.1Smycroft	andi.l	#$c0,d1
10891.1Smycroft	lsr.l	#6,d1		;put precision in upper word
10901.1Smycroft	swap	d1
10911.1Smycroft	or.l	d0,d1		;set up for round call
10921.1Smycroft	clr.l	d0		;force sticky to zero
10931.1Smycroft	bclr.b	#sign_bit,WBTEMP_EX(a6)
10941.1Smycroft	sne	WBTEMP_SGN(a6)
10951.1Smycroft	bsr.l	round		;round result to users rmode & prec
10961.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
10971.1Smycroft	beq	frcfpnr
10981.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
10991.1Smycroft	bra	frcfpnr
11001.1Smycroft*
11011.1Smycroft* Signs are unlike:
11021.1Smycroft*
11031.1Smycroftsub_diff:
11041.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;is dest the denorm?
11051.1Smycroft	bne.b	sub_s_srcd
11061.1Smycroftsub_s_destd:
11071.1Smycroft	lea.l	ETEMP(a6),a0
11081.1Smycroft	move.l	USER_FPCR(a6),d0
11091.1Smycroft	andi.l	#$30,d0
11101.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
11111.1Smycroft	move.l	USER_FPCR(a6),d1
11121.1Smycroft	andi.l	#$c0,d1
11131.1Smycroft	lsr.l	#6,d1		;put precision in upper word
11141.1Smycroft	swap	d1
11151.1Smycroft	or.l	d0,d1		;set up for round call
11161.1Smycroft	move.l	#$20000000,d0	;set sticky for round
11171.1Smycroft*
11181.1Smycroft* Since the dest is the denorm, the sign is the opposite of the
11191.1Smycroft* norm sign.
11201.1Smycroft*
11211.1Smycroft	eori.w	#$8000,ETEMP_EX(a6)	;flip sign on result
11221.1Smycroft	tst.w	ETEMP_EX(a6)
11231.1Smycroft	bgt.b	sub_s_dwr
11241.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
11251.1Smycroftsub_s_dwr:
11261.1Smycroft	bclr.b	#sign_bit,ETEMP_EX(a6)
11271.1Smycroft	sne	ETEMP_SGN(a6)
11281.1Smycroft	bsr.l	round		;round result to users rmode & prec
11291.1Smycroft	bfclr	ETEMP_SGN(a6){0:8}	;convert back to IEEE ext format
11301.1Smycroft	beq.b	sub_s_dclr
11311.1Smycroft	bset.b	#sign_bit,ETEMP_EX(a6)
11321.1Smycroftsub_s_dclr:
11331.1Smycroft	lea.l	WBTEMP(a6),a0
11341.1Smycroft	move.l	ETEMP(a6),(a0)	;write result to wbtemp
11351.1Smycroft	move.l	ETEMP_HI(a6),4(a0)
11361.1Smycroft	move.l	ETEMP_LO(a6),8(a0)
11371.1Smycroft	bra	sub_ckovf
11381.1Smycroftsub_s_srcd:
11391.1Smycroft	lea.l	FPTEMP(a6),a0
11401.1Smycroft	move.l	USER_FPCR(a6),d0
11411.1Smycroft	andi.l	#$30,d0
11421.1Smycroft	lsr.l	#4,d0		;put rmode in lower 2 bits
11431.1Smycroft	move.l	USER_FPCR(a6),d1
11441.1Smycroft	andi.l	#$c0,d1
11451.1Smycroft	lsr.l	#6,d1		;put precision in upper word
11461.1Smycroft	swap	d1
11471.1Smycroft	or.l	d0,d1		;set up for round call
11481.1Smycroft	move.l	#$20000000,d0	;set sticky for round
11491.1Smycroft	bclr.b	#sign_bit,FPTEMP_EX(a6)
11501.1Smycroft	sne	FPTEMP_SGN(a6)
11511.1Smycroft	bsr.l	round		;round result to users rmode & prec
11521.1Smycroft	bfclr	FPTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
11531.1Smycroft	beq.b	sub_s_sclr
11541.1Smycroft	bset.b	#sign_bit,FPTEMP_EX(a6)
11551.1Smycroftsub_s_sclr:
11561.1Smycroft	lea.l	WBTEMP(a6),a0
11571.1Smycroft	move.l	FPTEMP(a6),(a0)	;write result to wbtemp
11581.1Smycroft	move.l	FPTEMP_HI(a6),4(a0)
11591.1Smycroft	move.l	FPTEMP_LO(a6),8(a0)
11601.1Smycroft	tst.w	FPTEMP_EX(a6)
11611.1Smycroft	bgt	sub_ckovf
11621.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
11631.1Smycroftsub_ckovf:
11641.1Smycroft	move.w	WBTEMP_EX(a6),d0
11651.1Smycroft	andi.w	#$7fff,d0
11661.1Smycroft	cmpi.w	#$7fff,d0
11671.1Smycroft	bne	frcfpnr
11681.1Smycroft*
11691.1Smycroft* The result has overflowed to $7fff exponent.  Set I, ovfl,
11701.1Smycroft* and aovfl, and clr the mantissa (incorrectly set by the
11711.1Smycroft* round routine.)
11721.1Smycroft*
11731.1Smycroft	or.l	#inf_mask+ovfl_inx_mask,USER_FPSR(a6)	
11741.1Smycroft	clr.l	4(a0)
11751.1Smycroft	bra	frcfpnr
11761.1Smycroft*
11771.1Smycroft* Inst is fcmp.
11781.1Smycroft*
11791.1Smycroftwrap_cmp:
11801.1Smycroft	cmp.b	#$ff,DNRM_FLG(a6) ;if both ops denorm, 
11811.1Smycroft	beq	fix_stk		 ;restore to fpu
11821.1Smycroft*
11831.1Smycroft* One of the ops is denormalized.  Test for wrap condition
11841.1Smycroft* and complete the instruction.
11851.1Smycroft*
11861.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;check for dest denorm
11871.1Smycroft	bne.b	cmp_srcd
11881.1Smycroftcmp_destd:
11891.1Smycroft	bsr.l	ckinf_ns
11901.1Smycroft	bne	fix_stk
11911.1Smycroft	bfextu	ETEMP_EX(a6){1:15},d0	;get src exp (always pos)
11921.1Smycroft	bfexts	FPTEMP_EX(a6){1:15},d1	;get dest exp (always neg)
11931.1Smycroft	sub.l	d1,d0			;subtract dest from src
11941.1Smycroft	cmp.l	#$8000,d0
11951.1Smycroft	blt	fix_stk			;if less, not wrap case
11961.1Smycroft	tst.w	ETEMP_EX(a6)		;set N to ~sign_of(src)
11971.1Smycroft	bge	cmp_setn
11981.1Smycroft	rts
11991.1Smycroftcmp_srcd:
12001.1Smycroft	bsr.l	ckinf_nd
12011.1Smycroft	bne	fix_stk
12021.1Smycroft	bfextu	FPTEMP_EX(a6){1:15},d0	;get dest exp (always pos)
12031.1Smycroft	bfexts	ETEMP_EX(a6){1:15},d1	;get src exp (always neg)
12041.1Smycroft	sub.l	d1,d0			;subtract src from dest
12051.1Smycroft	cmp.l	#$8000,d0
12061.1Smycroft	blt	fix_stk			;if less, not wrap case
12071.1Smycroft	tst.w	FPTEMP_EX(a6)		;set N to sign_of(dest)
12081.1Smycroft	blt	cmp_setn
12091.1Smycroft	rts
12101.1Smycroftcmp_setn:
12111.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
12121.1Smycroft	rts
12131.1Smycroft
12141.1Smycroft*
12151.1Smycroft* Inst is fmul.
12161.1Smycroft*
12171.1Smycroftwrap_mul:
12181.1Smycroft	cmp.b	#$ff,DNRM_FLG(a6) ;if both ops denorm, 
12191.1Smycroft	beq	force_unf	;force an underflow (really!)
12201.1Smycroft*
12211.1Smycroft* One of the ops is denormalized.  Test for wrap condition
12221.1Smycroft* and complete the instruction.
12231.1Smycroft*
12241.1Smycroft	cmp.b	#$0f,DNRM_FLG(a6) ;check for dest denorm
12251.1Smycroft	bne.b	mul_srcd
12261.1Smycroftmul_destd:
12271.1Smycroft	bsr.l	ckinf_ns
12281.1Smycroft	bne	fix_stk
12291.1Smycroft	bfextu	ETEMP_EX(a6){1:15},d0	;get src exp (always pos)
12301.1Smycroft	bfexts	FPTEMP_EX(a6){1:15},d1	;get dest exp (always neg)
12311.1Smycroft	add.l	d1,d0			;subtract dest from src
12321.1Smycroft	bgt	fix_stk
12331.1Smycroft	bra	force_unf
12341.1Smycroftmul_srcd:
12351.1Smycroft	bsr.l	ckinf_nd
12361.1Smycroft	bne	fix_stk
12371.1Smycroft	bfextu	FPTEMP_EX(a6){1:15},d0	;get dest exp (always pos)
12381.1Smycroft	bfexts	ETEMP_EX(a6){1:15},d1	;get src exp (always neg)
12391.1Smycroft	add.l	d1,d0			;subtract src from dest
12401.1Smycroft	bgt	fix_stk
12411.1Smycroft	
12421.1Smycroft*
12431.1Smycroft* This code handles the case of the instruction resulting in 
12441.1Smycroft* an underflow condition.
12451.1Smycroft*
12461.1Smycroftforce_unf:
12471.1Smycroft	bclr.b	#E1,E_BYTE(a6)
12481.1Smycroft	or.l	#unfinx_mask,USER_FPSR(a6)
12491.1Smycroft	clr.w	NMNEXC(a6)
12501.1Smycroft	clr.b	WBTEMP_SGN(a6)
12511.1Smycroft	move.w	ETEMP_EX(a6),d0		;find the sign of the result
12521.1Smycroft	move.w	FPTEMP_EX(a6),d1
12531.1Smycroft	eor.w	d1,d0
12541.1Smycroft	andi.w	#$8000,d0
12551.1Smycroft	beq.b	frcunfcont
12561.1Smycroft	st.b	WBTEMP_SGN(a6)
12571.1Smycroftfrcunfcont:
12581.1Smycroft	lea	WBTEMP(a6),a0		;point a0 to memory location
12591.1Smycroft	move.w	CMDREG1B(a6),d0
12601.1Smycroft	btst.l	#6,d0			;test for forced precision
12611.1Smycroft	beq.b	frcunf_fpcr
12621.1Smycroft	btst.l	#2,d0			;check for double
12631.1Smycroft	bne.b	frcunf_dbl
12641.1Smycroft	move.l	#$1,d0			;inst is forced single
12651.1Smycroft	bra.b	frcunf_rnd
12661.1Smycroftfrcunf_dbl:
12671.1Smycroft	move.l	#$2,d0			;inst is forced double
12681.1Smycroft	bra.b	frcunf_rnd
12691.1Smycroftfrcunf_fpcr:
12701.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0	;inst not forced - use fpcr prec
12711.1Smycroftfrcunf_rnd:
12721.1Smycroft	bsr.l	unf_sub			;get correct result based on
12731.1Smycroft*					;round precision/mode.  This 
12741.1Smycroft*					;sets FPSR_CC correctly
12751.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
12761.1Smycroft	beq.b	frcfpn
12771.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
12781.1Smycroft	bra	frcfpn
12791.1Smycroft
12801.1Smycroft*
12811.1Smycroft* Write the result to the user's fpn.  All results must be HUGE to be
12821.1Smycroft* written; otherwise the results would have overflowed or underflowed.
12831.1Smycroft* If the rounding precision is single or double, the ovf_res routine
12841.1Smycroft* is needed to correctly supply the max value.
12851.1Smycroft*
12861.1Smycroftfrcfpnr:
12871.1Smycroft	move.w	CMDREG1B(a6),d0
12881.1Smycroft	btst.l	#6,d0			;test for forced precision
12891.1Smycroft	beq.b	frcfpn_fpcr
12901.1Smycroft	btst.l	#2,d0			;check for double
12911.1Smycroft	bne.b	frcfpn_dbl
12921.1Smycroft	move.l	#$1,d0			;inst is forced single
12931.1Smycroft	bra.b	frcfpn_rnd
12941.1Smycroftfrcfpn_dbl:
12951.1Smycroft	move.l	#$2,d0			;inst is forced double
12961.1Smycroft	bra.b	frcfpn_rnd
12971.1Smycroftfrcfpn_fpcr:
12981.1Smycroft	bfextu	FPCR_MODE(a6){0:2},d0	;inst not forced - use fpcr prec
12991.1Smycroft	tst.b	d0
13001.1Smycroft	beq.b	frcfpn			;if extended, write what you got
13011.1Smycroftfrcfpn_rnd:
13021.1Smycroft	bclr.b	#sign_bit,WBTEMP_EX(a6)
13031.1Smycroft	sne	WBTEMP_SGN(a6)
13041.1Smycroft	bsr.l	ovf_res			;get correct result based on
13051.1Smycroft*					;round precision/mode.  This 
13061.1Smycroft*					;sets FPSR_CC correctly
13071.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}	;convert back to IEEE ext format
13081.1Smycroft	beq.b	frcfpn_clr
13091.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
13101.1Smycroftfrcfpn_clr:
13111.1Smycroft	or.l	#ovfinx_mask,USER_FPSR(a6)
13121.1Smycroft* 
13131.1Smycroft* Perform the write.
13141.1Smycroft*
13151.1Smycroftfrcfpn:
13161.1Smycroft	bfextu	CMDREG1B(a6){6:3},d0	;extract fp destination register
13171.1Smycroft	cmpi.b	#3,d0
13181.1Smycroft	ble.b	frc0123			;check if dest is fp0-fp3
13191.1Smycroft	move.l	#7,d1
13201.1Smycroft	sub.l	d0,d1
13211.1Smycroft	clr.l	d0
13221.1Smycroft	bset.l	d1,d0
13231.1Smycroft	fmovem.x WBTEMP(a6),d0
13241.1Smycroft	rts
13251.1Smycroftfrc0123:
13261.2Smycroft	tst.b	d0
13271.1Smycroft	beq.b	frc0_dst
13281.1Smycroft	cmpi.b	#1,d0
13291.1Smycroft	beq.b	frc1_dst 
13301.1Smycroft	cmpi.b	#2,d0
13311.1Smycroft	beq.b	frc2_dst 
13321.1Smycroftfrc3_dst:
13331.1Smycroft	move.l	WBTEMP_EX(a6),USER_FP3(a6)
13341.1Smycroft	move.l	WBTEMP_HI(a6),USER_FP3+4(a6)
13351.1Smycroft	move.l	WBTEMP_LO(a6),USER_FP3+8(a6)
13361.1Smycroft	rts
13371.1Smycroftfrc2_dst:
13381.1Smycroft	move.l	WBTEMP_EX(a6),USER_FP2(a6)
13391.1Smycroft	move.l	WBTEMP_HI(a6),USER_FP2+4(a6)
13401.1Smycroft	move.l	WBTEMP_LO(a6),USER_FP2+8(a6)
13411.1Smycroft	rts
13421.1Smycroftfrc1_dst:
13431.1Smycroft	move.l	WBTEMP_EX(a6),USER_FP1(a6)
13441.1Smycroft	move.l	WBTEMP_HI(a6),USER_FP1+4(a6)
13451.1Smycroft	move.l	WBTEMP_LO(a6),USER_FP1+8(a6)
13461.1Smycroft	rts
13471.1Smycroftfrc0_dst:
13481.1Smycroft	move.l	WBTEMP_EX(a6),USER_FP0(a6)
13491.1Smycroft	move.l	WBTEMP_HI(a6),USER_FP0+4(a6)
13501.1Smycroft	move.l	WBTEMP_LO(a6),USER_FP0+8(a6)
13511.1Smycroft	rts
13521.1Smycroft
13531.1Smycroft*
13541.1Smycroft* Write etemp to fpn.
13551.1Smycroft* A check is made on enabled and signalled snan exceptions,
13561.1Smycroft* and the destination is not overwritten if this condition exists.
13571.1Smycroft* This code is designed to make fmoveins of unsupported data types
13581.1Smycroft* faster.
13591.1Smycroft*
13601.1Smycroftwr_etemp:
13611.1Smycroft	btst.b	#snan_bit,FPSR_EXCEPT(a6)	;if snan is set, and
13621.1Smycroft	beq.b	fmoveinc		;enabled, force restore
13631.1Smycroft	btst.b	#snan_bit,FPCR_ENABLE(a6) ;and don't overwrite
13641.1Smycroft	beq.b	fmoveinc		;the dest
13651.1Smycroft	move.l	ETEMP_EX(a6),FPTEMP_EX(a6)	;set up fptemp sign for 
13661.1Smycroft*						;snan handler
13671.1Smycroft	tst.b	ETEMP(a6)		;check for negative
13681.1Smycroft	blt.b	snan_neg
13691.1Smycroft	rts
13701.1Smycroftsnan_neg:
13711.1Smycroft	or.l	#neg_bit,USER_FPSR(a6)	;snan is negative; set N
13721.1Smycroft	rts
13731.1Smycroftfmoveinc:
13741.1Smycroft	clr.w	NMNEXC(a6)
13751.1Smycroft	bclr.b	#E1,E_BYTE(a6)
13761.1Smycroft	move.b	STAG(a6),d0		;check if stag is inf
13771.1Smycroft	andi.b	#$e0,d0
13781.1Smycroft	cmpi.b	#$40,d0
13791.1Smycroft	bne.b	fminc_cnan
13801.1Smycroft	or.l	#inf_mask,USER_FPSR(a6) ;if inf, nothing yet has set I
13811.1Smycroft	tst.w	LOCAL_EX(a0)		;check sign
13821.1Smycroft	bge.b	fminc_con
13831.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
13841.1Smycroft	bra	fminc_con
13851.1Smycroftfminc_cnan:
13861.1Smycroft	cmpi.b	#$60,d0			;check if stag is NaN
13871.1Smycroft	bne.b	fminc_czero
13881.1Smycroft	or.l	#nan_mask,USER_FPSR(a6) ;if nan, nothing yet has set NaN
13891.1Smycroft	move.l	ETEMP_EX(a6),FPTEMP_EX(a6)	;set up fptemp sign for 
13901.1Smycroft*						;snan handler
13911.1Smycroft	tst.w	LOCAL_EX(a0)		;check sign
13921.1Smycroft	bge.b	fminc_con
13931.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
13941.1Smycroft	bra	fminc_con
13951.1Smycroftfminc_czero:
13961.1Smycroft	cmpi.b	#$20,d0			;check if zero
13971.1Smycroft	bne.b	fminc_con
13981.1Smycroft	or.l	#z_mask,USER_FPSR(a6)	;if zero, set Z
13991.1Smycroft	tst.w	LOCAL_EX(a0)		;check sign
14001.1Smycroft	bge.b	fminc_con
14011.1Smycroft	or.l	#neg_mask,USER_FPSR(a6)
14021.1Smycroftfminc_con:
14031.1Smycroft	bfextu	CMDREG1B(a6){6:3},d0	;extract fp destination register
14041.1Smycroft	cmpi.b	#3,d0
14051.1Smycroft	ble.b	fp0123			;check if dest is fp0-fp3
14061.1Smycroft	move.l	#7,d1
14071.1Smycroft	sub.l	d0,d1
14081.1Smycroft	clr.l	d0
14091.1Smycroft	bset.l	d1,d0
14101.1Smycroft	fmovem.x ETEMP(a6),d0
14111.1Smycroft	rts
14121.1Smycroft
14131.1Smycroftfp0123:
14141.2Smycroft	tst.b	d0
14151.1Smycroft	beq.b	fp0_dst
14161.1Smycroft	cmpi.b	#1,d0
14171.1Smycroft	beq.b	fp1_dst 
14181.1Smycroft	cmpi.b	#2,d0
14191.1Smycroft	beq.b	fp2_dst 
14201.1Smycroftfp3_dst:
14211.1Smycroft	move.l	ETEMP_EX(a6),USER_FP3(a6)
14221.1Smycroft	move.l	ETEMP_HI(a6),USER_FP3+4(a6)
14231.1Smycroft	move.l	ETEMP_LO(a6),USER_FP3+8(a6)
14241.1Smycroft	rts
14251.1Smycroftfp2_dst:
14261.1Smycroft	move.l	ETEMP_EX(a6),USER_FP2(a6)
14271.1Smycroft	move.l	ETEMP_HI(a6),USER_FP2+4(a6)
14281.1Smycroft	move.l	ETEMP_LO(a6),USER_FP2+8(a6)
14291.1Smycroft	rts
14301.1Smycroftfp1_dst:
14311.1Smycroft	move.l	ETEMP_EX(a6),USER_FP1(a6)
14321.1Smycroft	move.l	ETEMP_HI(a6),USER_FP1+4(a6)
14331.1Smycroft	move.l	ETEMP_LO(a6),USER_FP1+8(a6)
14341.1Smycroft	rts
14351.1Smycroftfp0_dst:
14361.1Smycroft	move.l	ETEMP_EX(a6),USER_FP0(a6)
14371.1Smycroft	move.l	ETEMP_HI(a6),USER_FP0+4(a6)
14381.1Smycroft	move.l	ETEMP_LO(a6),USER_FP0+8(a6)
14391.1Smycroft	rts
14401.1Smycroft
14411.1Smycroftopclass3:
14421.1Smycroft	st.b	CU_ONLY(a6)
14431.1Smycroft	move.w	CMDREG1B(a6),d0	;check if packed moveout
14441.1Smycroft	andi.w	#$0c00,d0	;isolate last 2 bits of size field
14451.1Smycroft	cmpi.w	#$0c00,d0	;if size is 011 or 111, it is packed
14461.1Smycroft	beq.w	pack_out	;else it is norm or denorm
14471.1Smycroft	bra.w	mv_out
14481.1Smycroft
14491.1Smycroft	
14501.1Smycroft*
14511.1Smycroft*	MOVE OUT
14521.1Smycroft*
14531.1Smycroft
14541.1Smycroftmv_tbl:
14551.1Smycroft	dc.l	li
14561.1Smycroft	dc.l 	sgp
14571.1Smycroft	dc.l 	xp
14581.1Smycroft	dc.l 	mvout_end	;should never be taken
14591.1Smycroft	dc.l 	wi
14601.1Smycroft	dc.l 	dp
14611.1Smycroft	dc.l 	bi
14621.1Smycroft	dc.l 	mvout_end	;should never be taken
14631.1Smycroftmv_out:
14641.1Smycroft	bfextu	CMDREG1B(a6){3:3},d1	;put source specifier in d1
14651.1Smycroft	lea.l	mv_tbl,a0
14661.1Smycroft	move.l	(a0,d1*4),a0
14671.1Smycroft	jmp	(a0)
14681.1Smycroft
14691.1Smycroft*
14701.1Smycroft* This exit is for move-out to memory.  The aunfl bit is 
14711.1Smycroft* set if the result is inex and unfl is signalled.
14721.1Smycroft*
14731.1Smycroftmvout_end:
14741.1Smycroft	btst.b	#inex2_bit,FPSR_EXCEPT(a6)
14751.1Smycroft	beq.b	no_aufl
14761.1Smycroft	btst.b	#unfl_bit,FPSR_EXCEPT(a6)
14771.1Smycroft	beq.b	no_aufl
14781.1Smycroft	bset.b	#aunfl_bit,FPSR_AEXCEPT(a6)
14791.1Smycroftno_aufl:
14801.1Smycroft	clr.w	NMNEXC(a6)
14811.1Smycroft	bclr.b	#E1,E_BYTE(a6)
14821.1Smycroft	fmove.l	#0,FPSR			;clear any cc bits from res_func
14831.1Smycroft*
14841.1Smycroft* Return ETEMP to extended format from internal extended format so
14851.1Smycroft* that gen_except will have a correctly signed value for ovfl/unfl
14861.1Smycroft* handlers.
14871.1Smycroft*
14881.1Smycroft	bfclr	ETEMP_SGN(a6){0:8}
14891.1Smycroft	beq.b	mvout_con
14901.1Smycroft	bset.b	#sign_bit,ETEMP_EX(a6)
14911.1Smycroftmvout_con:
14921.1Smycroft	rts
14931.1Smycroft*
14941.1Smycroft* This exit is for move-out to int register.  The aunfl bit is 
14951.1Smycroft* not set in any case for this move.
14961.1Smycroft*
14971.1Smycroftmvouti_end:
14981.1Smycroft	clr.w	NMNEXC(a6)
14991.1Smycroft	bclr.b	#E1,E_BYTE(a6)
15001.1Smycroft	fmove.l	#0,FPSR			;clear any cc bits from res_func
15011.1Smycroft*
15021.1Smycroft* Return ETEMP to extended format from internal extended format so
15031.1Smycroft* that gen_except will have a correctly signed value for ovfl/unfl
15041.1Smycroft* handlers.
15051.1Smycroft*
15061.1Smycroft	bfclr	ETEMP_SGN(a6){0:8}
15071.1Smycroft	beq.b	mvouti_con
15081.1Smycroft	bset.b	#sign_bit,ETEMP_EX(a6)
15091.1Smycroftmvouti_con:
15101.1Smycroft	rts
15111.1Smycroft*
15121.1Smycroft* li is used to handle a long integer source specifier
15131.1Smycroft*
15141.1Smycroft
15151.1Smycroftli:
15161.1Smycroft	moveq.l	#4,d0		;set byte count
15171.1Smycroft
15181.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
15191.1Smycroft	bne.w	int_dnrm	;if so, branch
15201.1Smycroft
15211.1Smycroft	fmovem.x ETEMP(a6),fp0
15221.1Smycroft	fcmp.d	#:41dfffffffc00000,fp0
15231.1Smycroft* 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec
15241.1Smycroft	fbge.w	lo_plrg	
15251.1Smycroft	fcmp.d	#:c1e0000000000000,fp0
15261.1Smycroft* c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec
15271.1Smycroft	fble.w	lo_nlrg
15281.1Smycroft*
15291.1Smycroft* at this point, the answer is between the largest pos and neg values
15301.1Smycroft*
15311.1Smycroft	move.l	USER_FPCR(a6),d1	;use user's rounding mode
15321.1Smycroft	andi.l	#$30,d1
15331.1Smycroft	fmove.l	d1,fpcr
15341.1Smycroft	fmove.l	fp0,L_SCR1(a6)	;let the 040 perform conversion
15351.1Smycroft	fmove.l fpsr,d1
15361.1Smycroft	or.l	d1,USER_FPSR(a6)	;capture inex2/ainex if set
15371.1Smycroft	bra.w	int_wrt
15381.1Smycroft
15391.1Smycroft
15401.1Smycroftlo_plrg:
15411.1Smycroft	move.l	#$7fffffff,L_SCR1(a6)	;answer is largest positive int
15421.1Smycroft	fbeq.w	int_wrt			;exact answer
15431.1Smycroft	fcmp.d	#:41dfffffffe00000,fp0
15441.1Smycroft* 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec
15451.1Smycroft	fbge.w	int_operr		;set operr
15461.1Smycroft	bra.w	int_inx			;set inexact
15471.1Smycroft
15481.1Smycroftlo_nlrg:
15491.1Smycroft	move.l	#$80000000,L_SCR1(a6)
15501.1Smycroft	fbeq.w	int_wrt			;exact answer
15511.1Smycroft	fcmp.d	#:c1e0000000100000,fp0
15521.1Smycroft* c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec
15531.1Smycroft	fblt.w	int_operr		;set operr
15541.1Smycroft	bra.w	int_inx			;set inexact
15551.1Smycroft
15561.1Smycroft*
15571.1Smycroft* wi is used to handle a word integer source specifier
15581.1Smycroft*
15591.1Smycroft
15601.1Smycroftwi:
15611.1Smycroft	moveq.l	#2,d0		;set byte count
15621.1Smycroft
15631.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
15641.1Smycroft	bne.w	int_dnrm	;branch if so
15651.1Smycroft
15661.1Smycroft	fmovem.x ETEMP(a6),fp0
15671.1Smycroft	fcmp.s	#:46fffe00,fp0
15681.1Smycroft* 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec
15691.1Smycroft	fbge.w	wo_plrg	
15701.1Smycroft	fcmp.s	#:c7000000,fp0
15711.1Smycroft* c7000000 in sgl prec = c00e00008000000000000000 in ext prec
15721.1Smycroft	fble.w	wo_nlrg
15731.1Smycroft
15741.1Smycroft*
15751.1Smycroft* at this point, the answer is between the largest pos and neg values
15761.1Smycroft*
15771.1Smycroft	move.l	USER_FPCR(a6),d1	;use user's rounding mode
15781.1Smycroft	andi.l	#$30,d1
15791.1Smycroft	fmove.l	d1,fpcr
15801.1Smycroft	fmove.w	fp0,L_SCR1(a6)	;let the 040 perform conversion
15811.1Smycroft	fmove.l fpsr,d1
15821.1Smycroft	or.l	d1,USER_FPSR(a6)	;capture inex2/ainex if set
15831.1Smycroft	bra.w	int_wrt
15841.1Smycroft
15851.1Smycroftwo_plrg:
15861.1Smycroft	move.w	#$7fff,L_SCR1(a6)	;answer is largest positive int
15871.1Smycroft	fbeq.w	int_wrt			;exact answer
15881.1Smycroft	fcmp.s	#:46ffff00,fp0
15891.1Smycroft* 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec
15901.1Smycroft	fbge.w	int_operr		;set operr
15911.1Smycroft	bra.w	int_inx			;set inexact
15921.1Smycroft
15931.1Smycroftwo_nlrg:
15941.1Smycroft	move.w	#$8000,L_SCR1(a6)
15951.1Smycroft	fbeq.w	int_wrt			;exact answer
15961.1Smycroft	fcmp.s	#:c7000080,fp0
15971.1Smycroft* c7000080 in sgl prec = c00e00008000800000000000 in ext prec
15981.1Smycroft	fblt.w	int_operr		;set operr
15991.1Smycroft	bra.w	int_inx			;set inexact
16001.1Smycroft
16011.1Smycroft*
16021.1Smycroft* bi is used to handle a byte integer source specifier
16031.1Smycroft*
16041.1Smycroft
16051.1Smycroftbi:
16061.1Smycroft	moveq.l	#1,d0		;set byte count
16071.1Smycroft
16081.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
16091.1Smycroft	bne.w	int_dnrm	;branch if so
16101.1Smycroft
16111.1Smycroft	fmovem.x ETEMP(a6),fp0
16121.1Smycroft	fcmp.s	#:42fe0000,fp0
16131.1Smycroft* 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec
16141.1Smycroft	fbge.w	by_plrg	
16151.1Smycroft	fcmp.s	#:c3000000,fp0
16161.1Smycroft* c3000000 in sgl prec = c00600008000000000000000 in ext prec
16171.1Smycroft	fble.w	by_nlrg
16181.1Smycroft
16191.1Smycroft*
16201.1Smycroft* at this point, the answer is between the largest pos and neg values
16211.1Smycroft*
16221.1Smycroft	move.l	USER_FPCR(a6),d1	;use user's rounding mode
16231.1Smycroft	andi.l	#$30,d1
16241.1Smycroft	fmove.l	d1,fpcr
16251.1Smycroft	fmove.b	fp0,L_SCR1(a6)	;let the 040 perform conversion
16261.1Smycroft	fmove.l fpsr,d1
16271.1Smycroft	or.l	d1,USER_FPSR(a6)	;capture inex2/ainex if set
16281.1Smycroft	bra.w	int_wrt
16291.1Smycroft
16301.1Smycroftby_plrg:
16311.1Smycroft	move.b	#$7f,L_SCR1(a6)		;answer is largest positive int
16321.1Smycroft	fbeq.w	int_wrt			;exact answer
16331.1Smycroft	fcmp.s	#:42ff0000,fp0
16341.1Smycroft* 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec
16351.1Smycroft	fbge.w	int_operr		;set operr
16361.1Smycroft	bra.w	int_inx			;set inexact
16371.1Smycroft
16381.1Smycroftby_nlrg:
16391.1Smycroft	move.b	#$80,L_SCR1(a6)
16401.1Smycroft	fbeq.w	int_wrt			;exact answer
16411.1Smycroft	fcmp.s	#:c3008000,fp0
16421.1Smycroft* c3008000 in sgl prec = c00600008080000000000000 in ext prec
16431.1Smycroft	fblt.w	int_operr		;set operr
16441.1Smycroft	bra.w	int_inx			;set inexact
16451.1Smycroft
16461.1Smycroft*
16471.1Smycroft* Common integer routines
16481.1Smycroft*
16491.1Smycroft* int_drnrm---account for possible nonzero result for round up with positive
16501.1Smycroft* operand and round down for negative answer.  In the first case (result = 1)
16511.1Smycroft* byte-width (store in d0) of result must be honored.  In the second case,
16521.1Smycroft* -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out).
16531.1Smycroft
16541.1Smycroftint_dnrm:
16551.2Smycroft	clr.l	L_SCR1(a6)	; initialize result to 0
16561.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1	; d1 is the rounding mode
16571.1Smycroft	cmp.b	#2,d1		
16581.1Smycroft	bmi.b	int_inx		; if RN or RZ, done
16591.1Smycroft	bne.b	int_rp		; if RP, continue below
16601.1Smycroft	tst.w	ETEMP(a6)	; RM: store -1 in L_SCR1 if src is negative
16611.1Smycroft	bpl.b	int_inx		; otherwise result is 0
16621.1Smycroft	move.l	#-1,L_SCR1(a6)
16631.1Smycroft	bra.b	int_inx
16641.1Smycroftint_rp:
16651.1Smycroft	tst.w	ETEMP(a6)	; RP: store +1 of proper width in L_SCR1 if
16661.1Smycroft*				; source is greater than 0
16671.1Smycroft	bmi.b	int_inx		; otherwise, result is 0
16681.1Smycroft	lea	L_SCR1(a6),a1	; a1 is address of L_SCR1
16691.1Smycroft	adda.l	d0,a1		; offset by destination width -1
16701.1Smycroft	suba.l	#1,a1		
16711.1Smycroft	bset.b	#0,(a1)		; set low bit at a1 address
16721.1Smycroftint_inx:
16731.1Smycroft	ori.l	#inx2a_mask,USER_FPSR(a6)
16741.1Smycroft	bra.b	int_wrt
16751.1Smycroftint_operr:
16761.1Smycroft	fmovem.x fp0,FPTEMP(a6)	;FPTEMP must contain the extended
16771.1Smycroft*				;precision source that needs to be
16781.1Smycroft*				;converted to integer this is required
16791.1Smycroft*				;if the operr exception is enabled.
16801.1Smycroft*				;set operr/aiop (no inex2 on int ovfl)
16811.1Smycroft
16821.1Smycroft	ori.l	#opaop_mask,USER_FPSR(a6)
16831.1Smycroft*				;fall through to perform int_wrt
16841.1Smycroftint_wrt: 
16851.1Smycroft	move.l	EXC_EA(a6),a1	;load destination address
16861.1Smycroft	tst.l	a1		;check to see if it is a dest register
16871.1Smycroft	beq.b	wrt_dn		;write data register 
16881.1Smycroft	lea	L_SCR1(a6),a0	;point to supervisor source address
16891.1Smycroft	bsr.l	mem_write
16901.1Smycroft	bra.w	mvouti_end
16911.1Smycroft
16921.1Smycroftwrt_dn:
16931.1Smycroft	move.l	d0,-(sp)	;d0 currently contains the size to write
16941.1Smycroft	bsr.l	get_fline	;get_fline returns Dn in d0
16951.1Smycroft	andi.w	#$7,d0		;isolate register
16961.1Smycroft	move.l	(sp)+,d1	;get size
16971.1Smycroft	cmpi.l	#4,d1		;most frequent case
16981.1Smycroft	beq.b	sz_long
16991.1Smycroft	cmpi.l	#2,d1
17001.1Smycroft	bne.b	sz_con
17011.1Smycroft	or.l	#8,d0		;add 'word' size to register#
17021.1Smycroft	bra.b	sz_con
17031.1Smycroftsz_long:
17041.1Smycroft	or.l	#$10,d0		;add 'long' size to register#
17051.1Smycroftsz_con:
17061.1Smycroft	move.l	d0,d1		;reg_dest expects size:reg in d1
17071.1Smycroft	bsr.l	reg_dest	;load proper data register
17081.1Smycroft	bra.w	mvouti_end 
17091.1Smycroftxp:
17101.1Smycroft	lea	ETEMP(a6),a0
17111.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
17121.1Smycroft	sne	LOCAL_SGN(a0)
17131.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
17141.1Smycroft	bne.w	xdnrm
17151.1Smycroft	clr.l	d0
17161.1Smycroft	bra.b	do_fp		;do normal case
17171.1Smycroftsgp:
17181.1Smycroft	lea	ETEMP(a6),a0
17191.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
17201.1Smycroft	sne	LOCAL_SGN(a0)
17211.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
17221.1Smycroft	bne.w	sp_catas	;branch if so
17231.1Smycroft	move.w	LOCAL_EX(a0),d0
17241.1Smycroft	lea	sp_bnds,a1
17251.1Smycroft	cmp.w	(a1),d0
17261.1Smycroft	blt.w	sp_under
17271.1Smycroft	cmp.w	2(a1),d0
17281.1Smycroft	bgt.w	sp_over
17291.1Smycroft	move.l	#1,d0		;set destination format to single
17301.1Smycroft	bra.b	do_fp		;do normal case
17311.1Smycroftdp:
17321.1Smycroft	lea	ETEMP(a6),a0
17331.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
17341.1Smycroft	sne	LOCAL_SGN(a0)
17351.1Smycroft
17361.1Smycroft	btst.b	#7,STAG(a6)	;check for extended denorm
17371.1Smycroft	bne.w	dp_catas	;branch if so
17381.1Smycroft
17391.1Smycroft	move.w	LOCAL_EX(a0),d0
17401.1Smycroft	lea	dp_bnds,a1
17411.1Smycroft
17421.1Smycroft	cmp.w	(a1),d0
17431.1Smycroft	blt.w	dp_under
17441.1Smycroft	cmp.w	2(a1),d0
17451.1Smycroft	bgt.w	dp_over
17461.1Smycroft	
17471.1Smycroft	move.l	#2,d0		;set destination format to double
17481.1Smycroft*				;fall through to do_fp
17491.1Smycroft*
17501.1Smycroftdo_fp:
17511.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1	;rnd mode in d1
17521.1Smycroft	swap	d0			;rnd prec in upper word
17531.1Smycroft	add.l	d0,d1			;d1 has PREC/MODE info
17541.1Smycroft	
17551.1Smycroft	clr.l	d0			;clear g,r,s 
17561.1Smycroft
17571.1Smycroft	bsr.l	round			;round 
17581.1Smycroft
17591.1Smycroft	move.l	a0,a1
17601.1Smycroft	move.l	EXC_EA(a6),a0
17611.1Smycroft
17621.1Smycroft	bfextu	CMDREG1B(a6){3:3},d1	;extract destination format
17631.1Smycroft*					;at this point only the dest
17641.1Smycroft*					;formats sgl, dbl, ext are
17651.1Smycroft*					;possible
17661.1Smycroft	cmp.b	#2,d1
17671.1Smycroft	bgt.b	ddbl			;double=5, extended=2, single=1
17681.1Smycroft	bne.b	dsgl
17691.1Smycroft*					;fall through to dext
17701.1Smycroftdext:
17711.1Smycroft	bsr.l	dest_ext
17721.1Smycroft	bra.w	mvout_end
17731.1Smycroftdsgl:
17741.1Smycroft	bsr.l	dest_sgl
17751.1Smycroft	bra.w	mvout_end
17761.1Smycroftddbl:
17771.1Smycroft	bsr.l	dest_dbl
17781.1Smycroft	bra.w	mvout_end
17791.1Smycroft
17801.1Smycroft*
17811.1Smycroft* Handle possible denorm or catastrophic underflow cases here
17821.1Smycroft*
17831.1Smycroftxdnrm:
17841.1Smycroft	bsr.w	set_xop		;initialize WBTEMP
17851.1Smycroft	bset.b	#wbtemp15_bit,WB_BYTE(a6) ;set wbtemp15
17861.1Smycroft
17871.1Smycroft	move.l	a0,a1
17881.1Smycroft	move.l	EXC_EA(a6),a0	;a0 has the destination pointer
17891.1Smycroft	bsr.l	dest_ext	;store to memory
17901.1Smycroft	bset.b	#unfl_bit,FPSR_EXCEPT(a6)
17911.1Smycroft	bra.w	mvout_end
17921.1Smycroft	
17931.1Smycroftsp_under:
17941.1Smycroft	bset.b	#etemp15_bit,STAG(a6)
17951.1Smycroft
17961.1Smycroft	cmp.w	4(a1),d0
17971.1Smycroft	blt.b	sp_catas	;catastrophic underflow case	
17981.1Smycroft
17991.1Smycroft	move.l	#1,d0		;load in round precision
18001.1Smycroft	move.l	#sgl_thresh,d1	;load in single denorm threshold
18011.1Smycroft	bsr.l	dpspdnrm	;expects d1 to have the proper
18021.1Smycroft*				;denorm threshold
18031.1Smycroft	bsr.l	dest_sgl	;stores value to destination
18041.1Smycroft	bset.b	#unfl_bit,FPSR_EXCEPT(a6)
18051.1Smycroft	bra.w	mvout_end	;exit
18061.1Smycroft
18071.1Smycroftdp_under:
18081.1Smycroft	bset.b	#etemp15_bit,STAG(a6)
18091.1Smycroft
18101.1Smycroft	cmp.w	4(a1),d0
18111.1Smycroft	blt.b	dp_catas	;catastrophic underflow case
18121.1Smycroft		
18131.1Smycroft	move.l	#dbl_thresh,d1	;load in double precision threshold
18141.1Smycroft	move.l	#2,d0		
18151.1Smycroft	bsr.l	dpspdnrm	;expects d1 to have proper
18161.1Smycroft*				;denorm threshold
18171.1Smycroft*				;expects d0 to have round precision
18181.1Smycroft	bsr.l	dest_dbl	;store value to destination
18191.1Smycroft	bset.b	#unfl_bit,FPSR_EXCEPT(a6)
18201.1Smycroft	bra.w	mvout_end	;exit
18211.1Smycroft
18221.1Smycroft*
18231.1Smycroft* Handle catastrophic underflow cases here
18241.1Smycroft*
18251.1Smycroftsp_catas:
18261.1Smycroft* Temp fix for z bit set in unf_sub
18271.1Smycroft	move.l	USER_FPSR(a6),-(a7)
18281.1Smycroft
18291.1Smycroft	move.l	#1,d0		;set round precision to sgl
18301.1Smycroft
18311.1Smycroft	bsr.l	unf_sub		;a0 points to result
18321.1Smycroft
18331.1Smycroft	move.l	(a7)+,USER_FPSR(a6)
18341.1Smycroft
18351.1Smycroft	move.l	#1,d0
18361.1Smycroft	sub.w	d0,LOCAL_EX(a0) ;account for difference between
18371.1Smycroft*				;denorm/norm bias
18381.1Smycroft
18391.1Smycroft	move.l	a0,a1		;a1 has the operand input
18401.1Smycroft	move.l	EXC_EA(a6),a0	;a0 has the destination pointer
18411.1Smycroft	
18421.1Smycroft	bsr.l	dest_sgl	;store the result
18431.1Smycroft	ori.l	#unfinx_mask,USER_FPSR(a6)
18441.1Smycroft	bra.w	mvout_end
18451.1Smycroft	
18461.1Smycroftdp_catas:
18471.1Smycroft* Temp fix for z bit set in unf_sub
18481.1Smycroft	move.l	USER_FPSR(a6),-(a7)
18491.1Smycroft
18501.1Smycroft	move.l	#2,d0		;set round precision to dbl
18511.1Smycroft	bsr.l	unf_sub		;a0 points to result
18521.1Smycroft
18531.1Smycroft	move.l	(a7)+,USER_FPSR(a6)
18541.1Smycroft
18551.1Smycroft	move.l	#1,d0
18561.1Smycroft	sub.w	d0,LOCAL_EX(a0) ;account for difference between 
18571.1Smycroft*				;denorm/norm bias
18581.1Smycroft
18591.1Smycroft	move.l	a0,a1		;a1 has the operand input
18601.1Smycroft	move.l	EXC_EA(a6),a0	;a0 has the destination pointer
18611.1Smycroft	
18621.1Smycroft	bsr.l	dest_dbl	;store the result
18631.1Smycroft	ori.l	#unfinx_mask,USER_FPSR(a6)
18641.1Smycroft	bra.w	mvout_end
18651.1Smycroft
18661.1Smycroft*
18671.1Smycroft* Handle catastrophic overflow cases here
18681.1Smycroft*
18691.1Smycroftsp_over:
18701.1Smycroft* Temp fix for z bit set in unf_sub
18711.1Smycroft	move.l	USER_FPSR(a6),-(a7)
18721.1Smycroft
18731.1Smycroft	move.l	#1,d0
18741.1Smycroft	lea.l	FP_SCR1(a6),a0	;use FP_SCR1 for creating result
18751.1Smycroft	move.l	ETEMP_EX(a6),(a0)
18761.1Smycroft	move.l	ETEMP_HI(a6),4(a0)
18771.1Smycroft	move.l	ETEMP_LO(a6),8(a0)
18781.1Smycroft	bsr.l	ovf_res
18791.1Smycroft
18801.1Smycroft	move.l	(a7)+,USER_FPSR(a6)
18811.1Smycroft
18821.1Smycroft	move.l	a0,a1
18831.1Smycroft	move.l	EXC_EA(a6),a0
18841.1Smycroft	bsr.l	dest_sgl
18851.1Smycroft	or.l	#ovfinx_mask,USER_FPSR(a6)
18861.1Smycroft	bra.w	mvout_end
18871.1Smycroft
18881.1Smycroftdp_over:
18891.1Smycroft* Temp fix for z bit set in ovf_res
18901.1Smycroft	move.l	USER_FPSR(a6),-(a7)
18911.1Smycroft
18921.1Smycroft	move.l	#2,d0
18931.1Smycroft	lea.l	FP_SCR1(a6),a0	;use FP_SCR1 for creating result
18941.1Smycroft	move.l	ETEMP_EX(a6),(a0)
18951.1Smycroft	move.l	ETEMP_HI(a6),4(a0)
18961.1Smycroft	move.l	ETEMP_LO(a6),8(a0)
18971.1Smycroft	bsr.l	ovf_res
18981.1Smycroft
18991.1Smycroft	move.l	(a7)+,USER_FPSR(a6)
19001.1Smycroft
19011.1Smycroft	move.l	a0,a1
19021.1Smycroft	move.l	EXC_EA(a6),a0
19031.1Smycroft	bsr.l	dest_dbl
19041.1Smycroft	or.l	#ovfinx_mask,USER_FPSR(a6)
19051.1Smycroft	bra.w	mvout_end
19061.1Smycroft
19071.1Smycroft*
19081.1Smycroft* 	DPSPDNRM
19091.1Smycroft*
19101.1Smycroft* This subroutine takes an extended normalized number and denormalizes
19111.1Smycroft* it to the given round precision. This subroutine also decrements
19121.1Smycroft* the input operand's exponent by 1 to account for the fact that
19131.1Smycroft* dest_sgl or dest_dbl expects a normalized number's bias.
19141.1Smycroft*
19151.1Smycroft* Input: a0  points to a normalized number in internal extended format
19161.1Smycroft*	 d0  is the round precision (=1 for sgl; =2 for dbl)
19171.1Smycroft*	 d1  is the the single precision or double precision
19181.1Smycroft*	     denorm threshold
19191.1Smycroft*
19201.1Smycroft* Output: (In the format for dest_sgl or dest_dbl)
19211.1Smycroft*	 a0   points to the destination
19221.1Smycroft*   	 a1   points to the operand
19231.1Smycroft*
19241.1Smycroft* Exceptions: Reports inexact 2 exception by setting USER_FPSR bits
19251.1Smycroft*
19261.1Smycroftdpspdnrm:
19271.1Smycroft	move.l	d0,-(a7)	;save round precision
19281.1Smycroft	clr.l	d0		;clear initial g,r,s
19291.1Smycroft	bsr.l	dnrm_lp		;careful with d0, it's needed by round
19301.1Smycroft
19311.1Smycroft	bfextu	FPCR_MODE(a6){2:2},d1 ;get rounding mode
19321.1Smycroft	swap	d1
19331.1Smycroft	move.w	2(a7),d1	;set rounding precision 
19341.1Smycroft	swap	d1		;at this point d1 has PREC/MODE info
19351.1Smycroft	bsr.l	round		;round result, sets the inex bit in
19361.1Smycroft*				;USER_FPSR if needed
19371.1Smycroft
19381.1Smycroft	move.w	#1,d0
19391.1Smycroft	sub.w	d0,LOCAL_EX(a0) ;account for difference in denorm
19401.1Smycroft*				;vs norm bias
19411.1Smycroft
19421.1Smycroft	move.l	a0,a1		;a1 has the operand input
19431.1Smycroft	move.l	EXC_EA(a6),a0	;a0 has the destination pointer
19441.2Smycroft	addq.l	#4,a7		;pop stack
19451.1Smycroft	rts
19461.1Smycroft*
19471.1Smycroft* SET_XOP initialized WBTEMP with the value pointed to by a0
19481.1Smycroft* input: a0 points to input operand in the internal extended format
19491.1Smycroft*
19501.1Smycroftset_xop:
19511.1Smycroft	move.l	LOCAL_EX(a0),WBTEMP_EX(a6)
19521.1Smycroft	move.l	LOCAL_HI(a0),WBTEMP_HI(a6)
19531.1Smycroft	move.l	LOCAL_LO(a0),WBTEMP_LO(a6)
19541.1Smycroft	bfclr	WBTEMP_SGN(a6){0:8}
19551.1Smycroft	beq.b	sxop
19561.1Smycroft	bset.b	#sign_bit,WBTEMP_EX(a6)
19571.1Smycroftsxop:
19581.1Smycroft	bfclr	STAG(a6){5:4}	;clear wbtm66,wbtm1,wbtm0,sbit
19591.1Smycroft	rts
19601.1Smycroft*
19611.1Smycroft*	P_MOVE
19621.1Smycroft*
19631.1Smycroftp_movet:
19641.1Smycroft	dc.l	p_move
19651.1Smycroft	dc.l	p_movez
19661.1Smycroft	dc.l	p_movei
19671.1Smycroft	dc.l	p_moven
19681.1Smycroft	dc.l	p_move
19691.1Smycroftp_regd:
19701.1Smycroft	dc.l	p_dyd0
19711.1Smycroft	dc.l	p_dyd1
19721.1Smycroft	dc.l	p_dyd2
19731.1Smycroft	dc.l	p_dyd3
19741.1Smycroft	dc.l	p_dyd4
19751.1Smycroft	dc.l	p_dyd5
19761.1Smycroft	dc.l	p_dyd6
19771.1Smycroft	dc.l	p_dyd7
19781.1Smycroft
19791.1Smycroftpack_out:
19801.1Smycroft 	lea.l	p_movet,a0	;load jmp table address
19811.1Smycroft	move.w	STAG(a6),d0	;get source tag
19821.1Smycroft	bfextu	d0{16:3},d0	;isolate source bits
19831.1Smycroft	move.l	(a0,d0.w*4),a0	;load a0 with routine label for tag
19841.1Smycroft	jmp	(a0)		;go to the routine
19851.1Smycroft
19861.1Smycroftp_write:
19871.1Smycroft	move.l	#$0c,d0 	;get byte count
19881.1Smycroft	move.l	EXC_EA(a6),a1	;get the destination address
19891.1Smycroft	bsr 	mem_write	;write the user's destination
19901.2Smycroft	clr.b	CU_SAVEPC(a6) ;set the cu save pc to all 0's
19911.1Smycroft
19921.1Smycroft*
19931.1Smycroft* Also note that the dtag must be set to norm here - this is because 
19941.1Smycroft* the 040 uses the dtag to execute the correct microcode.
19951.1Smycroft*
19961.1Smycroft        bfclr    DTAG(a6){0:3}  ;set dtag to norm
19971.1Smycroft
19981.1Smycroft	rts
19991.1Smycroft
20001.1Smycroft* Notes on handling of special case (zero, inf, and nan) inputs:
20011.1Smycroft*	1. Operr is not signalled if the k-factor is greater than 18.
20021.1Smycroft*	2. Per the manual, status bits are not set.
20031.1Smycroft*
20041.1Smycroft
20051.1Smycroftp_move:
20061.1Smycroft	move.w	CMDREG1B(a6),d0
20071.1Smycroft	btst.l	#kfact_bit,d0	;test for dynamic k-factor
20081.1Smycroft	beq.b	statick		;if clear, k-factor is static
20091.1Smycroftdynamick:
20101.1Smycroft	bfextu	d0{25:3},d0	;isolate register for dynamic k-factor
20111.1Smycroft	lea	p_regd,a0
20121.1Smycroft	move.l	(a0,d0*4),a0
20131.1Smycroft	jmp	(a0)
20141.1Smycroftstatick:
20151.1Smycroft	andi.w	#$007f,d0	;get k-factor
20161.1Smycroft	bfexts	d0{25:7},d0	;sign extend d0 for bindec
20171.1Smycroft	lea.l	ETEMP(a6),a0	;a0 will point to the packed decimal
20181.1Smycroft	bsr.l	bindec		;perform the convert; data at a6
20191.1Smycroft	lea.l	FP_SCR1(a6),a0	;load a0 with result address
20201.1Smycroft	bra.l	p_write
20211.1Smycroftp_movez:
20221.1Smycroft	lea.l	ETEMP(a6),a0	;a0 will point to the packed decimal
20231.1Smycroft	clr.w	2(a0)		;clear lower word of exp
20241.1Smycroft	clr.l	4(a0)		;load second lword of ZERO
20251.1Smycroft	clr.l	8(a0)		;load third lword of ZERO
20261.1Smycroft	bra.w	p_write		;go write results
20271.1Smycroftp_movei:
20281.1Smycroft	fmove.l	#0,FPSR		;clear aiop
20291.1Smycroft	lea.l	ETEMP(a6),a0	;a0 will point to the packed decimal
20301.1Smycroft	clr.w	2(a0)		;clear lower word of exp
20311.1Smycroft	bra.w	p_write		;go write the result
20321.1Smycroftp_moven:
20331.1Smycroft	lea.l	ETEMP(a6),a0	;a0 will point to the packed decimal
20341.1Smycroft	clr.w	2(a0)		;clear lower word of exp
20351.1Smycroft	bra.w	p_write		;go write the result
20361.1Smycroft
20371.1Smycroft*
20381.1Smycroft* Routines to read the dynamic k-factor from Dn.
20391.1Smycroft*
20401.1Smycroftp_dyd0:
20411.1Smycroft	move.l	USER_D0(a6),d0
20421.1Smycroft	bra.b	statick
20431.1Smycroftp_dyd1:
20441.1Smycroft	move.l	USER_D1(a6),d0
20451.1Smycroft	bra.b	statick
20461.1Smycroftp_dyd2:
20471.1Smycroft	move.l	d2,d0
20481.1Smycroft	bra.b	statick
20491.1Smycroftp_dyd3:
20501.1Smycroft	move.l	d3,d0
20511.1Smycroft	bra.b	statick
20521.1Smycroftp_dyd4:
20531.1Smycroft	move.l	d4,d0
20541.1Smycroft	bra.b	statick
20551.1Smycroftp_dyd5:
20561.1Smycroft	move.l	d5,d0
20571.1Smycroft	bra.b	statick
20581.1Smycroftp_dyd6:
20591.1Smycroft	move.l	d6,d0
20601.1Smycroft	bra.w	statick
20611.1Smycroftp_dyd7:
20621.1Smycroft	move.l	d7,d0
20631.1Smycroft	bra.w	statick
20641.1Smycroft
20651.1Smycroft	end
2066