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