| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | | | 
					
						
							|  |  |  | |	res_func.sa 3.9 7/29/91 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Normalizes denormalized numbers if necessary and updates the | 
					
						
							|  |  |  | | stack frame.  The function is then restored back into the | 
					
						
							|  |  |  | | machine and the 040 completes the operation.  This routine | 
					
						
							|  |  |  | | is only used by the unsupported data type/format handler. | 
					
						
							|  |  |  | | (Exception vector 55). | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For packed move out (fmove.p fpm,<ea>) the operation is | 
					
						
							|  |  |  | | completed here; data is packed and moved to user memory.
 | 
					
						
							|  |  |  | | The stack is restored to the 040 only in the case of a | 
					
						
							|  |  |  | | reportable exception in the conversion. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |		Copyright (C) Motorola, Inc. 1990 | 
					
						
							|  |  |  | |			All Rights Reserved | 
					
						
							|  |  |  | | | 
					
						
							| 
									
										
										
										
											2006-02-11 17:55:48 -08:00
										 |  |  | |       For details on the license for this file, please see the | 
					
						
							|  |  |  | |       file, README, in this same directory. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | RES_FUNC:    |idnt    2,1 | Motorola 040 Floating Point Software Package | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	|section	8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "fpsp.h" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sp_bnds:	.short	0x3f81,0x407e | 
					
						
							|  |  |  | 		.short	0x3f6a,0x0000 | 
					
						
							|  |  |  | dp_bnds:	.short	0x3c01,0x43fe | 
					
						
							|  |  |  | 		.short	0x3bcd,0x0000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	|xref	mem_write | 
					
						
							|  |  |  | 	|xref	bindec | 
					
						
							|  |  |  | 	|xref	get_fline | 
					
						
							|  |  |  | 	|xref	round | 
					
						
							|  |  |  | 	|xref	denorm | 
					
						
							|  |  |  | 	|xref	dest_ext | 
					
						
							|  |  |  | 	|xref	dest_dbl | 
					
						
							|  |  |  | 	|xref	dest_sgl | 
					
						
							|  |  |  | 	|xref	unf_sub | 
					
						
							|  |  |  | 	|xref	nrm_set | 
					
						
							|  |  |  | 	|xref	dnrm_lp | 
					
						
							|  |  |  | 	|xref	ovf_res | 
					
						
							|  |  |  | 	|xref	reg_dest | 
					
						
							|  |  |  | 	|xref	t_ovfl | 
					
						
							|  |  |  | 	|xref	t_unfl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.global	res_func
 | 
					
						
							|  |  |  | 	.global	p_move
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | res_func: | 
					
						
							|  |  |  | 	clrb	DNRM_FLG(%a6) | 
					
						
							|  |  |  | 	clrb	RES_FLG(%a6) | 
					
						
							|  |  |  | 	clrb	CU_ONLY(%a6) | 
					
						
							|  |  |  | 	tstb	DY_MO_FLG(%a6) | 
					
						
							|  |  |  | 	beqs	monadic | 
					
						
							|  |  |  | dyadic: | 
					
						
							|  |  |  | 	btstb	#7,DTAG(%a6)	|if dop = norm=000, zero=001, | 
					
						
							|  |  |  | |				;inf=010 or nan=011
 | 
					
						
							|  |  |  | 	beqs	monadic		|then branch | 
					
						
							|  |  |  | |				;else denorm
 | 
					
						
							|  |  |  | | HANDLE DESTINATION DENORM HERE | 
					
						
							|  |  |  | |				;set dtag to norm
 | 
					
						
							|  |  |  | |				;write the tag & fpte15 to the fstack
 | 
					
						
							|  |  |  | 	leal	FPTEMP(%a6),%a0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bsr	nrm_set		|normalize number (exp will go negative) | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	dpos | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | dpos: | 
					
						
							|  |  |  | 	bfclr	DTAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0 | 
					
						
							|  |  |  | 	bsetb	#4,DTAG(%a6)	|set FPTE15 | 
					
						
							|  |  |  | 	orb	#0x0f,DNRM_FLG(%a6) | 
					
						
							|  |  |  | monadic: | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	btstb	#direction_bit,CMDREG1B(%a6)	|check direction | 
					
						
							|  |  |  | 	bne	opclass3			|it is a mv out | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | At this point, only opclass 0 and 2 possible | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|if sop = norm=000, zero=001, | 
					
						
							|  |  |  | |				;inf=010 or nan=011
 | 
					
						
							|  |  |  | 	bne	mon_dnrm	|else denorm | 
					
						
							|  |  |  | 	tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would | 
					
						
							|  |  |  | 	bne	normal		|require normalization of denorm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | At this point: | 
					
						
							|  |  |  | |	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a | 
					
						
							|  |  |  | |				fmove = $00  fsmove = $40  fdmove = $44 | 
					
						
							|  |  |  | |				fsqrt = $05* fssqrt = $41  fdsqrt = $45 | 
					
						
							|  |  |  | |				(*fsqrt reencoded to $05) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0	|get command register | 
					
						
							|  |  |  | 	andil	#0x7f,%d0			|strip to only command word | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | 
					
						
							|  |  |  | | fdsqrt are possible. | 
					
						
							|  |  |  | | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) | 
					
						
							|  |  |  | | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	btstl	#0,%d0 | 
					
						
							|  |  |  | 	bne	normal			|weed out fsqrt instructions | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | cu_norm handles fmove in instructions with normalized inputs. | 
					
						
							|  |  |  | | The routine round is used to correctly round the input for the | 
					
						
							|  |  |  | | destination precision and mode. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_norm: | 
					
						
							|  |  |  | 	st	CU_ONLY(%a6)		|set cu-only inst flag | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	andib	#0x3b,%d0		|isolate bits to select inst | 
					
						
							|  |  |  | 	tstb	%d0 | 
					
						
							|  |  |  | 	beql	cu_nmove	|if zero, it is an fmove | 
					
						
							|  |  |  | 	cmpib	#0x18,%d0 | 
					
						
							|  |  |  | 	beql	cu_nabs		|if $18, it is fabs | 
					
						
							|  |  |  | 	cmpib	#0x1a,%d0 | 
					
						
							|  |  |  | 	beql	cu_nneg		|if $1a, it is fneg | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is ftst.  Check the source operand and set the cc's accordingly. | 
					
						
							|  |  |  | | No write is done, so simply rts. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_ntst: | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d0 | 
					
						
							|  |  |  | 	bclrl	#15,%d0 | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	beqs	cu_ntpo | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) |set N | 
					
						
							|  |  |  | cu_ntpo: | 
					
						
							|  |  |  | 	cmpiw	#0x7fff,%d0	|test for inf/nan | 
					
						
							|  |  |  | 	bnes	cu_ntcz | 
					
						
							|  |  |  | 	tstl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	bnes	cu_ntn | 
					
						
							|  |  |  | 	tstl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	bnes	cu_ntn | 
					
						
							|  |  |  | 	orl	#inf_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cu_ntn: | 
					
						
							|  |  |  | 	orl	#nan_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
					
						
							|  |  |  | |						;snan handler
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cu_ntcz: | 
					
						
							|  |  |  | 	tstl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	bnel	cu_ntsx | 
					
						
							|  |  |  | 	tstl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	bnel	cu_ntsx | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | cu_ntsx: | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fabs.  Execute the absolute value function on the input. | 
					
						
							|  |  |  | | Branch to the fmove code.  If the operand is NaN, do nothing. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nabs: | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#5,%d0			|test for NaN or zero | 
					
						
							|  |  |  | 	bne	wr_etemp		|if either, simply write it | 
					
						
							|  |  |  | 	bclrb	#7,LOCAL_EX(%a0)		|do abs | 
					
						
							|  |  |  | 	bras	cu_nmove		|fmove code will finish | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fneg.  Execute the negate value function on the input. | 
					
						
							|  |  |  | | Fall though to the fmove code.  If the operand is NaN, do nothing. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nneg: | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#5,%d0			|test for NaN or zero | 
					
						
							|  |  |  | 	bne	wr_etemp		|if either, simply write it | 
					
						
							|  |  |  | 	bchgb	#7,LOCAL_EX(%a0)		|do neg | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fmove.  This code also handles all result writes. | 
					
						
							|  |  |  | | If bit 2 is set, round is forced to double.  If it is clear, | 
					
						
							|  |  |  | | and bit 6 is set, round is forced to single.  If both are clear, | 
					
						
							|  |  |  | | the round precision is found in the fpcr.  If the rounding precision | 
					
						
							|  |  |  | | is double or single, round the result before the write. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nmove: | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0 | 
					
						
							|  |  |  | 	andib	#0xe0,%d0			|isolate stag bits | 
					
						
							|  |  |  | 	bne	wr_etemp		|if not norm, simply write it | 
					
						
							|  |  |  | 	btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
					
						
							|  |  |  | 	bne	cu_nmrd | 
					
						
							|  |  |  | 	btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
					
						
							|  |  |  | 	bne	cu_nmrs | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move or operation is not with forced precision.  Test for | 
					
						
							|  |  |  | | nan or inf as the input; if so, simply write it to FPn.  Use the
 | 
					
						
							|  |  |  | | FPCR_MODE byte to get rounding on norms and zeros. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nmnr: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#0:#2},%d0 | 
					
						
							|  |  |  | 	tstb	%d0			|check for extended | 
					
						
							|  |  |  | 	beq	cu_wrexn		|if so, just write result | 
					
						
							|  |  |  | 	cmpib	#1,%d0			|check for single | 
					
						
							|  |  |  | 	beq	cu_nmrs			|fall through to double | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move is fdmove or round precision is double. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nmrd: | 
					
						
							|  |  |  | 	movel	#2,%d0			|set up the size for denorm | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d1		|compare exponent to double threshold | 
					
						
							|  |  |  | 	andw	#0x7fff,%d1 | 
					
						
							|  |  |  | 	cmpw	#0x3c01,%d1 | 
					
						
							|  |  |  | 	bls	cu_nunfl | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
					
						
							|  |  |  | 	orl	#0x00020000,%d1		|or in rprec (double) | 
					
						
							|  |  |  | 	clrl	%d0			|clear g,r,s for round | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0)	|convert to internal format | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	bsrl	round | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8} | 
					
						
							|  |  |  | 	beqs	cu_nmrdc | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | cu_nmrdc: | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d1		|check for overflow | 
					
						
							|  |  |  | 	andw	#0x7fff,%d1 | 
					
						
							|  |  |  | 	cmpw	#0x43ff,%d1 | 
					
						
							|  |  |  | 	bge	cu_novfl		|take care of overflow case | 
					
						
							|  |  |  | 	bra	cu_wrexn | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move is fsmove or round precision is single. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nmrs: | 
					
						
							|  |  |  | 	movel	#1,%d0 | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d1 | 
					
						
							|  |  |  | 	andw	#0x7fff,%d1 | 
					
						
							|  |  |  | 	cmpw	#0x3f81,%d1 | 
					
						
							|  |  |  | 	bls	cu_nunfl | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1 | 
					
						
							|  |  |  | 	orl	#0x00010000,%d1 | 
					
						
							|  |  |  | 	clrl	%d0 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	bsrl	round | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8} | 
					
						
							|  |  |  | 	beqs	cu_nmrsc | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | cu_nmrsc: | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d1 | 
					
						
							|  |  |  | 	andw	#0x7FFF,%d1 | 
					
						
							|  |  |  | 	cmpw	#0x407f,%d1 | 
					
						
							|  |  |  | 	blt	cu_wrexn | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The operand is above precision boundaries.  Use t_ovfl to | 
					
						
							|  |  |  | | generate the correct value. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_novfl: | 
					
						
							|  |  |  | 	bsr	t_ovfl | 
					
						
							|  |  |  | 	bra	cu_wrexn | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The operand is below precision boundaries.  Use denorm to | 
					
						
							|  |  |  | | generate the correct value. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_nunfl: | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	bsr	denorm | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	cu_nucont | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | cu_nucont: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1 | 
					
						
							|  |  |  | 	btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
					
						
							|  |  |  | 	bne	inst_d | 
					
						
							|  |  |  | 	btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
					
						
							|  |  |  | 	bne	inst_s | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	moveb	FPCR_MODE(%a6),%d1 | 
					
						
							|  |  |  | 	lsrb	#6,%d1 | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	bra	inst_sd | 
					
						
							|  |  |  | inst_d: | 
					
						
							|  |  |  | 	orl	#0x00020000,%d1 | 
					
						
							|  |  |  | 	bra	inst_sd | 
					
						
							|  |  |  | inst_s: | 
					
						
							|  |  |  | 	orl	#0x00010000,%d1 | 
					
						
							|  |  |  | inst_sd: | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	bsrl	round | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8} | 
					
						
							|  |  |  | 	beqs	cu_nuflp | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | cu_nuflp: | 
					
						
							|  |  |  | 	btstb	#inex2_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	beqs	cu_nuninx | 
					
						
							|  |  |  | 	orl	#aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFL | 
					
						
							|  |  |  | cu_nuninx: | 
					
						
							|  |  |  | 	tstl	LOCAL_HI(%a0)		|test for zero | 
					
						
							|  |  |  | 	bnes	cu_nunzro | 
					
						
							|  |  |  | 	tstl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	bnes	cu_nunzro | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The mantissa is zero from the denorm loop.  Check sign and rmode | 
					
						
							|  |  |  | | to see if rounding should have occurred which would leave the lsb. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0		|isolate rmode | 
					
						
							|  |  |  | 	cmpil	#0x20,%d0 | 
					
						
							|  |  |  | 	blts	cu_nzro | 
					
						
							|  |  |  | 	bnes	cu_nrp | 
					
						
							|  |  |  | cu_nrm: | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)	|if positive, set lsb | 
					
						
							|  |  |  | 	bges	cu_nzro | 
					
						
							|  |  |  | 	btstb	#7,FPCR_MODE(%a6) |check for double | 
					
						
							|  |  |  | 	beqs	cu_nincs | 
					
						
							|  |  |  | 	bras	cu_nincd | 
					
						
							|  |  |  | cu_nrp: | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)	|if positive, set lsb | 
					
						
							|  |  |  | 	blts	cu_nzro | 
					
						
							|  |  |  | 	btstb	#7,FPCR_MODE(%a6) |check for double | 
					
						
							|  |  |  | 	beqs	cu_nincs | 
					
						
							|  |  |  | cu_nincd: | 
					
						
							|  |  |  | 	orl	#0x800,LOCAL_LO(%a0) |inc for double | 
					
						
							|  |  |  | 	bra	cu_nunzro | 
					
						
							|  |  |  | cu_nincs: | 
					
						
							|  |  |  | 	orl	#0x100,LOCAL_HI(%a0) |inc for single | 
					
						
							|  |  |  | 	bra	cu_nunzro | 
					
						
							|  |  |  | cu_nzro: | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0 | 
					
						
							|  |  |  | 	andib	#0xe0,%d0 | 
					
						
							|  |  |  | 	cmpib	#0x40,%d0		|check if input was tagged zero | 
					
						
							|  |  |  | 	beqs	cu_numv | 
					
						
							|  |  |  | cu_nunzro: | 
					
						
							|  |  |  | 	orl	#unfl_mask,USER_FPSR(%a6) |set unfl | 
					
						
							|  |  |  | cu_numv: | 
					
						
							|  |  |  | 	movel	(%a0),ETEMP(%a6) | 
					
						
							|  |  |  | 	movel	4(%a0),ETEMP_HI(%a6) | 
					
						
							|  |  |  | 	movel	8(%a0),ETEMP_LO(%a6) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Write the result to memory, setting the fpsr cc bits.  NaN and Inf | 
					
						
							|  |  |  | | bypass cu_wrexn. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_wrexn: | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|test for zero | 
					
						
							|  |  |  | 	beqs	cu_wrzero | 
					
						
							|  |  |  | 	cmpw	#0x8000,LOCAL_EX(%a0)	|test for zero | 
					
						
							|  |  |  | 	bnes	cu_wreon | 
					
						
							|  |  |  | cu_wrzero: | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6)	|set Z bit | 
					
						
							|  |  |  | cu_wreon: | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	bpl	wr_etemp | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | HANDLE SOURCE DENORM HERE | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |				;clear denorm stag to norm
 | 
					
						
							|  |  |  | |				;write the new tag & ete15 to the fstack
 | 
					
						
							|  |  |  | mon_dnrm: | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | At this point, check for the cases in which normalizing the | 
					
						
							|  |  |  | | denorm produces incorrect results. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would | 
					
						
							|  |  |  | 	bnes	nrm_src		|require normalization of denorm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | At this point: | 
					
						
							|  |  |  | |	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a | 
					
						
							|  |  |  | |				fmove = $00  fsmove = $40  fdmove = $44 | 
					
						
							|  |  |  | |				fsqrt = $05* fssqrt = $41  fdsqrt = $45 | 
					
						
							|  |  |  | |				(*fsqrt reencoded to $05) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0	|get command register | 
					
						
							|  |  |  | 	andil	#0x7f,%d0			|strip to only command word | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | 
					
						
							|  |  |  | | fdsqrt are possible. | 
					
						
							|  |  |  | | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) | 
					
						
							|  |  |  | | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	btstl	#0,%d0 | 
					
						
							|  |  |  | 	bnes	nrm_src		|weed out fsqrt instructions | 
					
						
							|  |  |  | 	st	CU_ONLY(%a6)	|set cu-only inst flag | 
					
						
							|  |  |  | 	bra	cu_dnrm		|fmove, fabs, fneg, ftst | 
					
						
							|  |  |  | |				;cases go to cu_dnrm
 | 
					
						
							|  |  |  | nrm_src: | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	bsr	nrm_set		|normalize number (exponent will go | 
					
						
							|  |  |  | |				; negative)
 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	spos | 
					
						
							|  |  |  | 	bsetb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | spos: | 
					
						
							|  |  |  | 	bfclr	STAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0 | 
					
						
							|  |  |  | 	bsetb	#4,STAG(%a6)	|set ETE15 | 
					
						
							|  |  |  | 	orb	#0xf0,DNRM_FLG(%a6) | 
					
						
							|  |  |  | normal: | 
					
						
							|  |  |  | 	tstb	DNRM_FLG(%a6)	|check if any of the ops were denorms | 
					
						
							|  |  |  | 	bne	ck_wrap		|if so, check if it is a potential | 
					
						
							|  |  |  | |				;wrap-around case
 | 
					
						
							|  |  |  | fix_stk: | 
					
						
							|  |  |  | 	moveb	#0xfe,CU_SAVEPC(%a6) | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	st	RES_FLG(%a6)	|indicate that a restore is needed | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and | 
					
						
							|  |  |  | | ftst) completely in software without an frestore to the 040. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dnrm: | 
					
						
							|  |  |  | 	st	CU_ONLY(%a6) | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	andib	#0x3b,%d0		|isolate bits to select inst | 
					
						
							|  |  |  | 	tstb	%d0 | 
					
						
							|  |  |  | 	beql	cu_dmove	|if zero, it is an fmove | 
					
						
							|  |  |  | 	cmpib	#0x18,%d0 | 
					
						
							|  |  |  | 	beql	cu_dabs		|if $18, it is fabs | 
					
						
							|  |  |  | 	cmpib	#0x1a,%d0 | 
					
						
							|  |  |  | 	beql	cu_dneg		|if $1a, it is fneg | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is ftst.  Check the source operand and set the cc's accordingly. | 
					
						
							|  |  |  | | No write is done, so simply rts. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dtst: | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d0 | 
					
						
							|  |  |  | 	bclrl	#15,%d0 | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	beqs	cu_dtpo | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) |set N | 
					
						
							|  |  |  | cu_dtpo: | 
					
						
							|  |  |  | 	cmpiw	#0x7fff,%d0	|test for inf/nan | 
					
						
							|  |  |  | 	bnes	cu_dtcz | 
					
						
							|  |  |  | 	tstl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	bnes	cu_dtn | 
					
						
							|  |  |  | 	tstl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	bnes	cu_dtn | 
					
						
							|  |  |  | 	orl	#inf_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cu_dtn: | 
					
						
							|  |  |  | 	orl	#nan_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
					
						
							|  |  |  | |						;snan handler
 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cu_dtcz: | 
					
						
							|  |  |  | 	tstl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	bnel	cu_dtsx | 
					
						
							|  |  |  | 	tstl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	bnel	cu_dtsx | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | cu_dtsx: | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fabs.  Execute the absolute value function on the input. | 
					
						
							|  |  |  | | Branch to the fmove code. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dabs: | 
					
						
							|  |  |  | 	bclrb	#7,LOCAL_EX(%a0)		|do abs | 
					
						
							|  |  |  | 	bras	cu_dmove		|fmove code will finish | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fneg.  Execute the negate value function on the input. | 
					
						
							|  |  |  | | Fall though to the fmove code. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dneg: | 
					
						
							|  |  |  | 	bchgb	#7,LOCAL_EX(%a0)		|do neg | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fmove.  This code also handles all result writes. | 
					
						
							|  |  |  | | If bit 2 is set, round is forced to double.  If it is clear, | 
					
						
							|  |  |  | | and bit 6 is set, round is forced to single.  If both are clear, | 
					
						
							|  |  |  | | the round precision is found in the fpcr.  If the rounding precision | 
					
						
							|  |  |  | | is double or single, the result is zero, and the mode is checked | 
					
						
							|  |  |  | | to determine if the lsb of the result should be set. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dmove: | 
					
						
							|  |  |  | 	btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
					
						
							|  |  |  | 	bne	cu_dmrd | 
					
						
							|  |  |  | 	btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
					
						
							|  |  |  | 	bne	cu_dmrs | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move or operation is not with forced precision.  Use the | 
					
						
							|  |  |  | | FPCR_MODE byte to get rounding. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dmnr: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#0:#2},%d0 | 
					
						
							|  |  |  | 	tstb	%d0			|check for extended | 
					
						
							|  |  |  | 	beq	cu_wrexd		|if so, just write result | 
					
						
							|  |  |  | 	cmpib	#1,%d0			|check for single | 
					
						
							|  |  |  | 	beq	cu_dmrs			|fall through to double | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move is fdmove or round precision is double.  Result is zero. | 
					
						
							|  |  |  | | Check rmode for rp or rm and set lsb accordingly. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dmrd: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|check sign | 
					
						
							|  |  |  | 	blts	cu_dmdn | 
					
						
							|  |  |  | 	cmpib	#3,%d1			|check for rp | 
					
						
							|  |  |  | 	bne	cu_dpd			|load double pos zero | 
					
						
							|  |  |  | 	bra	cu_dpdr			|load double pos zero w/lsb | 
					
						
							|  |  |  | cu_dmdn: | 
					
						
							|  |  |  | 	cmpib	#2,%d1			|check for rm | 
					
						
							|  |  |  | 	bne	cu_dnd			|load double neg zero | 
					
						
							|  |  |  | 	bra	cu_dndr			|load double neg zero w/lsb | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The move is fsmove or round precision is single.  Result is zero. | 
					
						
							|  |  |  | | Check for rp or rm and set lsb accordingly. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dmrs: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|check sign | 
					
						
							|  |  |  | 	blts	cu_dmsn | 
					
						
							|  |  |  | 	cmpib	#3,%d1			|check for rp | 
					
						
							|  |  |  | 	bne	cu_spd			|load single pos zero | 
					
						
							|  |  |  | 	bra	cu_spdr			|load single pos zero w/lsb | 
					
						
							|  |  |  | cu_dmsn: | 
					
						
							|  |  |  | 	cmpib	#2,%d1			|check for rm | 
					
						
							|  |  |  | 	bne	cu_snd			|load single neg zero | 
					
						
							|  |  |  | 	bra	cu_sndr			|load single neg zero w/lsb | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The precision is extended, so the result in etemp is correct. | 
					
						
							|  |  |  | | Simply set unfl (not inex2 or aunfl) and write the result to | 
					
						
							|  |  |  | | the correct fp register. | 
					
						
							|  |  |  | cu_wrexd: | 
					
						
							|  |  |  | 	orl	#unfl_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	beq	wr_etemp | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | These routines write +/- zero in double format.  The routines | 
					
						
							|  |  |  | | cu_dpdr and cu_dndr set the double lsb. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_dpd: | 
					
						
							|  |  |  | 	movel	#0x3c010000,LOCAL_EX(%a0)	|force pos double zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_dpdr: | 
					
						
							|  |  |  | 	movel	#0x3c010000,LOCAL_EX(%a0)	|force pos double zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	movel	#0x800,LOCAL_LO(%a0)	|with lsb set | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_dnd: | 
					
						
							|  |  |  | 	movel	#0xbc010000,LOCAL_EX(%a0)	|force pos double zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_dndr: | 
					
						
							|  |  |  | 	movel	#0xbc010000,LOCAL_EX(%a0)	|force pos double zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	movel	#0x800,LOCAL_LO(%a0)	|with lsb set | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | These routines write +/- zero in single format.  The routines | 
					
						
							|  |  |  | | cu_dpdr and cu_dndr set the single lsb. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | cu_spd: | 
					
						
							|  |  |  | 	movel	#0x3f810000,LOCAL_EX(%a0)	|force pos single zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_spdr: | 
					
						
							|  |  |  | 	movel	#0x3f810000,LOCAL_EX(%a0)	|force pos single zero | 
					
						
							|  |  |  | 	movel	#0x100,LOCAL_HI(%a0)	|with lsb set | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_snd: | 
					
						
							|  |  |  | 	movel	#0xbf810000,LOCAL_EX(%a0)	|force pos single zero | 
					
						
							|  |  |  | 	clrl	LOCAL_HI(%a0) | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | cu_sndr: | 
					
						
							|  |  |  | 	movel	#0xbf810000,LOCAL_EX(%a0)	|force pos single zero | 
					
						
							|  |  |  | 	movel	#0x100,LOCAL_HI(%a0)	|with lsb set | 
					
						
							|  |  |  | 	clrl	LOCAL_LO(%a0) | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	wr_etemp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This code checks for 16-bit overflow conditions on dyadic | 
					
						
							|  |  |  | | operations which are not restorable into the floating-point | 
					
						
							|  |  |  | | unit and must be completed in software.  Basically, this | 
					
						
							|  |  |  | | condition exists with a very large norm and a denorm.  One | 
					
						
							|  |  |  | | of the operands must be denormalized to enter this code. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Flags used: | 
					
						
							|  |  |  | |	DY_MO_FLG contains 0 for monadic op, $ff for dyadic | 
					
						
							|  |  |  | |	DNRM_FLG contains $00 for neither op denormalized | 
					
						
							|  |  |  | |	                  $0f for the destination op denormalized | 
					
						
							|  |  |  | |	                  $f0 for the source op denormalized | 
					
						
							|  |  |  | |	                  $ff for both ops denormalized | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The wrap-around condition occurs for add, sub, div, and cmp | 
					
						
							|  |  |  | | when | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |	abs(dest_exp - src_exp) >= $8000 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | and for mul when | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |	(dest_exp + src_exp) < $0 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | we must process the operation here if this case is true. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The rts following the frcfpn routine is the exit from res_func | 
					
						
							|  |  |  | | for this condition.  The restore flag (RES_FLG) is left clear. | 
					
						
							|  |  |  | | No frestore is done unless an exception is to be reported. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For fadd: | 
					
						
							|  |  |  | |	if(sign_of(dest) != sign_of(src)) | 
					
						
							|  |  |  | |		replace exponent of src with $3fff (keep sign) | 
					
						
							|  |  |  | |		use fpu to perform dest+new_src (user's rmode and X) | 
					
						
							|  |  |  | |		clr sticky | 
					
						
							|  |  |  | |	else | 
					
						
							|  |  |  | |		set sticky | 
					
						
							|  |  |  | |	call round with user's precision and mode | 
					
						
							|  |  |  | |	move result to fpn and wbtemp | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For fsub: | 
					
						
							|  |  |  | |	if(sign_of(dest) == sign_of(src)) | 
					
						
							|  |  |  | |		replace exponent of src with $3fff (keep sign) | 
					
						
							|  |  |  | |		use fpu to perform dest+new_src (user's rmode and X) | 
					
						
							|  |  |  | |		clr sticky | 
					
						
							|  |  |  | |	else | 
					
						
							|  |  |  | |		set sticky | 
					
						
							|  |  |  | |	call round with user's precision and mode | 
					
						
							|  |  |  | |	move result to fpn and wbtemp | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For fdiv/fsgldiv: | 
					
						
							|  |  |  | |	if(both operands are denorm) | 
					
						
							|  |  |  | |		restore_to_fpu;
 | 
					
						
							|  |  |  | |	if(dest is norm) | 
					
						
							|  |  |  | |		force_ovf;
 | 
					
						
							|  |  |  | |	else(dest is denorm) | 
					
						
							|  |  |  | |		force_unf: | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For fcmp: | 
					
						
							|  |  |  | |	if(dest is norm) | 
					
						
							|  |  |  | |		N = sign_of(dest);
 | 
					
						
							|  |  |  | |	else(dest is denorm) | 
					
						
							|  |  |  | |		N = sign_of(src);
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | For fmul: | 
					
						
							|  |  |  | |	if(both operands are denorm) | 
					
						
							|  |  |  | |		force_unf;
 | 
					
						
							|  |  |  | |	if((dest_exp + src_exp) < 0) | 
					
						
							|  |  |  | |		force_unf: | 
					
						
							|  |  |  | |	else | 
					
						
							|  |  |  | |		restore_to_fpu;
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | local equates: | 
					
						
							|  |  |  | 	.set	addcode,0x22 | 
					
						
							|  |  |  | 	.set	subcode,0x28 | 
					
						
							|  |  |  | 	.set	mulcode,0x23 | 
					
						
							|  |  |  | 	.set	divcode,0x20 | 
					
						
							|  |  |  | 	.set	cmpcode,0x38 | 
					
						
							|  |  |  | ck_wrap: | 
					
						
							|  |  |  | 	| tstb	DY_MO_FLG(%a6)	;check for fsqrt
 | 
					
						
							|  |  |  | 	beq	fix_stk		|if zero, it is fsqrt | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x3b,%d0		|strip to command bits | 
					
						
							|  |  |  | 	cmpiw	#addcode,%d0 | 
					
						
							|  |  |  | 	beq	wrap_add | 
					
						
							|  |  |  | 	cmpiw	#subcode,%d0 | 
					
						
							|  |  |  | 	beq	wrap_sub | 
					
						
							|  |  |  | 	cmpiw	#mulcode,%d0 | 
					
						
							|  |  |  | 	beq	wrap_mul | 
					
						
							|  |  |  | 	cmpiw	#cmpcode,%d0 | 
					
						
							|  |  |  | 	beq	wrap_cmp | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fdiv. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wrap_div: | 
					
						
							|  |  |  | 	cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
					
						
							|  |  |  | 	beq	fix_stk		 |restore to fpu | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | One of the ops is denormalized.  Test for wrap condition | 
					
						
							|  |  |  | | and force the result. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
					
						
							|  |  |  | 	bnes	div_srcd | 
					
						
							|  |  |  | div_destd: | 
					
						
							|  |  |  | 	bsrl	ckinf_ns | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
					
						
							|  |  |  | 	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract dest from src | 
					
						
							|  |  |  | 	cmpl	#0x7fff,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	clrb	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d1 | 
					
						
							|  |  |  | 	eorw	%d1,%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	beq	force_unf | 
					
						
							|  |  |  | 	st	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bra	force_unf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ckinf_ns: | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0		|check source tag for inf or nan | 
					
						
							|  |  |  | 	bra	ck_in_com | 
					
						
							|  |  |  | ckinf_nd: | 
					
						
							|  |  |  | 	moveb	DTAG(%a6),%d0		|check destination tag for inf or nan | 
					
						
							|  |  |  | ck_in_com: | 
					
						
							|  |  |  | 	andib	#0x60,%d0			|isolate tag bits | 
					
						
							|  |  |  | 	cmpb	#0x40,%d0			|is it inf? | 
					
						
							|  |  |  | 	beq	nan_or_inf		|not wrap case | 
					
						
							|  |  |  | 	cmpb	#0x60,%d0			|is it nan? | 
					
						
							|  |  |  | 	beq	nan_or_inf		|yes, not wrap case? | 
					
						
							|  |  |  | 	cmpb	#0x20,%d0			|is it a zero? | 
					
						
							|  |  |  | 	beq	nan_or_inf		|yes | 
					
						
							|  |  |  | 	clrl	%d0 | 
					
						
							|  |  |  | 	rts				|then ; it is either a zero of norm,
 | 
					
						
							|  |  |  | |					;check wrap case
 | 
					
						
							|  |  |  | nan_or_inf: | 
					
						
							|  |  |  | 	moveql	#-1,%d0 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | div_srcd: | 
					
						
							|  |  |  | 	bsrl	ckinf_nd | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
					
						
							|  |  |  | 	bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract src from dest | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	clrb	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d1 | 
					
						
							|  |  |  | 	eorw	%d1,%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	beqs	force_ovf | 
					
						
							|  |  |  | 	st	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This code handles the case of the instruction resulting in | 
					
						
							|  |  |  | | an overflow condition. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | force_ovf: | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 	orl	#ovfl_inx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0		|point a0 to memory location | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#6,%d0			|test for forced precision | 
					
						
							|  |  |  | 	beqs	frcovf_fpcr | 
					
						
							|  |  |  | 	btstl	#2,%d0			|check for double | 
					
						
							|  |  |  | 	bnes	frcovf_dbl | 
					
						
							|  |  |  | 	movel	#0x1,%d0			|inst is forced single | 
					
						
							|  |  |  | 	bras	frcovf_rnd | 
					
						
							|  |  |  | frcovf_dbl: | 
					
						
							|  |  |  | 	movel	#0x2,%d0			|inst is forced double | 
					
						
							|  |  |  | 	bras	frcovf_rnd | 
					
						
							|  |  |  | frcovf_fpcr: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
					
						
							|  |  |  | frcovf_rnd: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | The 881/882 does not set inex2 for the following case, so the | 
					
						
							|  |  |  | | line is commented out to be compatible with 881/882 | 
					
						
							|  |  |  | |	tst.b	%d0 | 
					
						
							|  |  |  | |	beq.b	frcovf_x | 
					
						
							|  |  |  | |	or.l	#inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | |frcovf_x: | 
					
						
							|  |  |  | 	bsrl	ovf_res			|get correct result based on | 
					
						
							|  |  |  | |					;round precision/mode.  This
 | 
					
						
							|  |  |  | |					;sets FPSR_CC correctly
 | 
					
						
							|  |  |  | |					;returns in external format
 | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8} | 
					
						
							|  |  |  | 	beq	frcfpn | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpn | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fadd. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wrap_add: | 
					
						
							|  |  |  | 	cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
					
						
							|  |  |  | 	beq	fix_stk		 |restore to fpu | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | One of the ops is denormalized.  Test for wrap condition | 
					
						
							|  |  |  | | and complete the instruction. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
					
						
							|  |  |  | 	bnes	add_srcd | 
					
						
							|  |  |  | add_destd: | 
					
						
							|  |  |  | 	bsrl	ckinf_ns | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
					
						
							|  |  |  | 	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract dest from src | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	bra	add_wrap | 
					
						
							|  |  |  | add_srcd: | 
					
						
							|  |  |  | 	bsrl	ckinf_nd | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
					
						
							|  |  |  | 	bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract src from dest | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Check the signs of the operands.  If they are unlike, the fpu | 
					
						
							|  |  |  | | can be used to add the norm and 1.0 with the sign of the | 
					
						
							|  |  |  | | denorm and it will correctly generate the result in extended | 
					
						
							|  |  |  | | precision.  We can then call round with no sticky and the result | 
					
						
							|  |  |  | | will be correct for the user's rounding mode and precision.  If | 
					
						
							|  |  |  | | the signs are the same, we call round with the sticky bit set | 
					
						
							|  |  |  | | and the result will be correct for the user's rounding mode and | 
					
						
							|  |  |  | | precision. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | add_wrap: | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d1 | 
					
						
							|  |  |  | 	eorw	%d1,%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	beq	add_same | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The signs are unlike. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
					
						
							|  |  |  | 	bnes	add_u_srcd | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
					
						
							|  |  |  | 	movew	%d0,FPTEMP_EX(%a6) |in the denorm | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	fmovel	%d0,%fpcr		|set up users rmode and X | 
					
						
							|  |  |  | 	fmovex	ETEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	faddx	FPTEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
					
						
							|  |  |  | 	fmovel	%fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
					
						
							|  |  |  | 	fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	clrl	%d0		|force sticky to zero | 
					
						
							|  |  |  | 	bclrb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beq	frcfpnr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | add_u_srcd: | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
					
						
							|  |  |  | 	movew	%d0,ETEMP_EX(%a6) |in the denorm | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	fmovel	%d0,%fpcr		|set up users rmode and X | 
					
						
							|  |  |  | 	fmovex	ETEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	faddx	FPTEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	fmovel	%fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
					
						
							|  |  |  | 	fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	clrl	%d0		|force sticky to zero | 
					
						
							|  |  |  | 	bclrb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	WBTEMP_SGN(%a6)	|use internal format for round | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beq	frcfpnr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Signs are alike: | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | add_same: | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
					
						
							|  |  |  | 	bnes	add_s_srcd | 
					
						
							|  |  |  | add_s_destd: | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	movel	#0x20000000,%d0	|set sticky for round | 
					
						
							|  |  |  | 	bclrb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	ETEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	ETEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	add_s_dclr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | add_s_dclr: | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	ETEMP(%a6),(%a0)	|write result to wbtemp | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	tstw	ETEMP_EX(%a6) | 
					
						
							|  |  |  | 	bgt	add_ckovf | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	add_ckovf | 
					
						
							|  |  |  | add_s_srcd: | 
					
						
							|  |  |  | 	leal	FPTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	movel	#0x20000000,%d0	|set sticky for round | 
					
						
							|  |  |  | 	bclrb	#sign_bit,FPTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	FPTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	FPTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	add_s_sclr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,FPTEMP_EX(%a6) | 
					
						
							|  |  |  | add_s_sclr: | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	FPTEMP(%a6),(%a0)	|write result to wbtemp | 
					
						
							|  |  |  | 	movel	FPTEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	FPTEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	tstw	FPTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bgt	add_ckovf | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | add_ckovf: | 
					
						
							|  |  |  | 	movew	WBTEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x7fff,%d0 | 
					
						
							|  |  |  | 	cmpiw	#0x7fff,%d0 | 
					
						
							|  |  |  | 	bne	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The result has overflowed to $7fff exponent.  Set I, ovfl, | 
					
						
							|  |  |  | | and aovfl, and clr the mantissa (incorrectly set by the | 
					
						
							|  |  |  | | round routine.) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	orl	#inf_mask+ovfl_inx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	clrl	4(%a0) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fsub. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wrap_sub: | 
					
						
							|  |  |  | 	cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
					
						
							|  |  |  | 	beq	fix_stk		 |restore to fpu | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | One of the ops is denormalized.  Test for wrap condition | 
					
						
							|  |  |  | | and complete the instruction. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
					
						
							|  |  |  | 	bnes	sub_srcd | 
					
						
							|  |  |  | sub_destd: | 
					
						
							|  |  |  | 	bsrl	ckinf_ns | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
					
						
							|  |  |  | 	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract src from dest | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	bra	sub_wrap | 
					
						
							|  |  |  | sub_srcd: | 
					
						
							|  |  |  | 	bsrl	ckinf_nd | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
					
						
							|  |  |  | 	bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract dest from src | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Check the signs of the operands.  If they are alike, the fpu | 
					
						
							|  |  |  | | can be used to subtract from the norm 1.0 with the sign of the | 
					
						
							|  |  |  | | denorm and it will correctly generate the result in extended | 
					
						
							|  |  |  | | precision.  We can then call round with no sticky and the result | 
					
						
							|  |  |  | | will be correct for the user's rounding mode and precision.  If | 
					
						
							|  |  |  | | the signs are unlike, we call round with the sticky bit set | 
					
						
							|  |  |  | | and the result will be correct for the user's rounding mode and | 
					
						
							|  |  |  | | precision. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | sub_wrap: | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d1 | 
					
						
							|  |  |  | 	eorw	%d1,%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	bne	sub_diff | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The signs are alike. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
					
						
							|  |  |  | 	bnes	sub_u_srcd | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
					
						
							|  |  |  | 	movew	%d0,FPTEMP_EX(%a6) |in the denorm | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	fmovel	%d0,%fpcr		|set up users rmode and X | 
					
						
							|  |  |  | 	fmovex	FPTEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	fsubx	ETEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	fmovel	%fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
					
						
							|  |  |  | 	fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	clrl	%d0		|force sticky to zero | 
					
						
							|  |  |  | 	bclrb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beq	frcfpnr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | sub_u_srcd: | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
					
						
							|  |  |  | 	movew	%d0,ETEMP_EX(%a6) |in the denorm | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	fmovel	%d0,%fpcr		|set up users rmode and X | 
					
						
							|  |  |  | 	fmovex	FPTEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	fsubx	ETEMP(%a6),%fp0 | 
					
						
							|  |  |  | 	fmovel	%fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
					
						
							|  |  |  | 	fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	clrl	%d0		|force sticky to zero | 
					
						
							|  |  |  | 	bclrb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beq	frcfpnr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Signs are unlike: | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | sub_diff: | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
					
						
							|  |  |  | 	bnes	sub_s_srcd | 
					
						
							|  |  |  | sub_s_destd: | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	movel	#0x20000000,%d0	|set sticky for round | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Since the dest is the denorm, the sign is the opposite of the | 
					
						
							|  |  |  | | norm sign. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	eoriw	#0x8000,ETEMP_EX(%a6)	|flip sign on result | 
					
						
							|  |  |  | 	tstw	ETEMP_EX(%a6) | 
					
						
							|  |  |  | 	bgts	sub_s_dwr | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | sub_s_dwr: | 
					
						
							|  |  |  | 	bclrb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	ETEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	ETEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	sub_s_dclr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | sub_s_dclr: | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	ETEMP(%a6),(%a0)	|write result to wbtemp | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	bra	sub_ckovf | 
					
						
							|  |  |  | sub_s_srcd: | 
					
						
							|  |  |  | 	leal	FPTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d0 | 
					
						
							|  |  |  | 	andil	#0x30,%d0 | 
					
						
							|  |  |  | 	lsrl	#4,%d0		|put rmode in lower 2 bits | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1 | 
					
						
							|  |  |  | 	andil	#0xc0,%d1 | 
					
						
							|  |  |  | 	lsrl	#6,%d1		|put precision in upper word | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	orl	%d0,%d1		|set up for round call | 
					
						
							|  |  |  | 	movel	#0x20000000,%d0	|set sticky for round | 
					
						
							|  |  |  | 	bclrb	#sign_bit,FPTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	FPTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	round		|round result to users rmode & prec | 
					
						
							|  |  |  | 	bfclr	FPTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	sub_s_sclr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,FPTEMP_EX(%a6) | 
					
						
							|  |  |  | sub_s_sclr: | 
					
						
							|  |  |  | 	leal	WBTEMP(%a6),%a0 | 
					
						
							|  |  |  | 	movel	FPTEMP(%a6),(%a0)	|write result to wbtemp | 
					
						
							|  |  |  | 	movel	FPTEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	FPTEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	tstw	FPTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bgt	sub_ckovf | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | sub_ckovf: | 
					
						
							|  |  |  | 	movew	WBTEMP_EX(%a6),%d0 | 
					
						
							|  |  |  | 	andiw	#0x7fff,%d0 | 
					
						
							|  |  |  | 	cmpiw	#0x7fff,%d0 | 
					
						
							|  |  |  | 	bne	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | The result has overflowed to $7fff exponent.  Set I, ovfl, | 
					
						
							|  |  |  | | and aovfl, and clr the mantissa (incorrectly set by the | 
					
						
							|  |  |  | | round routine.) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	orl	#inf_mask+ovfl_inx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	clrl	4(%a0) | 
					
						
							|  |  |  | 	bra	frcfpnr | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fcmp. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wrap_cmp: | 
					
						
							|  |  |  | 	cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
					
						
							|  |  |  | 	beq	fix_stk		 |restore to fpu | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | One of the ops is denormalized.  Test for wrap condition | 
					
						
							|  |  |  | | and complete the instruction. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
					
						
							|  |  |  | 	bnes	cmp_srcd | 
					
						
							|  |  |  | cmp_destd: | 
					
						
							|  |  |  | 	bsrl	ckinf_ns | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
					
						
							|  |  |  | 	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract dest from src | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	tstw	ETEMP_EX(%a6)		|set N to ~sign_of(src) | 
					
						
							|  |  |  | 	bge	cmp_setn | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cmp_srcd: | 
					
						
							|  |  |  | 	bsrl	ckinf_nd | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
					
						
							|  |  |  | 	bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
					
						
							|  |  |  | 	subl	%d1,%d0			|subtract src from dest | 
					
						
							|  |  |  | 	cmpl	#0x8000,%d0 | 
					
						
							|  |  |  | 	blt	fix_stk			|if less, not wrap case | 
					
						
							|  |  |  | 	tstw	FPTEMP_EX(%a6)		|set N to sign_of(dest) | 
					
						
							|  |  |  | 	blt	cmp_setn | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | cmp_setn: | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Inst is fmul. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wrap_mul: | 
					
						
							|  |  |  | 	cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
					
						
							|  |  |  | 	beq	force_unf	|force an underflow (really!) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | One of the ops is denormalized.  Test for wrap condition | 
					
						
							|  |  |  | | and complete the instruction. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
					
						
							|  |  |  | 	bnes	mul_srcd | 
					
						
							|  |  |  | mul_destd: | 
					
						
							|  |  |  | 	bsrl	ckinf_ns | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
					
						
							|  |  |  | 	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
					
						
							|  |  |  | 	addl	%d1,%d0			|subtract dest from src | 
					
						
							|  |  |  | 	bgt	fix_stk | 
					
						
							|  |  |  | 	bra	force_unf | 
					
						
							|  |  |  | mul_srcd: | 
					
						
							|  |  |  | 	bsrl	ckinf_nd | 
					
						
							|  |  |  | 	bne	fix_stk | 
					
						
							|  |  |  | 	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
					
						
							|  |  |  | 	bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
					
						
							|  |  |  | 	addl	%d1,%d0			|subtract src from dest | 
					
						
							|  |  |  | 	bgt	fix_stk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This code handles the case of the instruction resulting in | 
					
						
							|  |  |  | | an underflow condition. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | force_unf: | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 	orl	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 	clrb	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
					
						
							|  |  |  | 	movew	FPTEMP_EX(%a6),%d1 | 
					
						
							|  |  |  | 	eorw	%d1,%d0 | 
					
						
							|  |  |  | 	andiw	#0x8000,%d0 | 
					
						
							|  |  |  | 	beqs	frcunfcont | 
					
						
							|  |  |  | 	st	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | frcunfcont: | 
					
						
							|  |  |  | 	lea	WBTEMP(%a6),%a0		|point a0 to memory location | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#6,%d0			|test for forced precision | 
					
						
							|  |  |  | 	beqs	frcunf_fpcr | 
					
						
							|  |  |  | 	btstl	#2,%d0			|check for double | 
					
						
							|  |  |  | 	bnes	frcunf_dbl | 
					
						
							|  |  |  | 	movel	#0x1,%d0			|inst is forced single | 
					
						
							|  |  |  | 	bras	frcunf_rnd | 
					
						
							|  |  |  | frcunf_dbl: | 
					
						
							|  |  |  | 	movel	#0x2,%d0			|inst is forced double | 
					
						
							|  |  |  | 	bras	frcunf_rnd | 
					
						
							|  |  |  | frcunf_fpcr: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
					
						
							|  |  |  | frcunf_rnd: | 
					
						
							|  |  |  | 	bsrl	unf_sub			|get correct result based on | 
					
						
							|  |  |  | |					;round precision/mode.  This
 | 
					
						
							|  |  |  | |					;sets FPSR_CC correctly
 | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	frcfpn | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	bra	frcfpn | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Write the result to the user's fpn.  All results must be HUGE to be | 
					
						
							|  |  |  | | written; otherwise the results would have overflowed or underflowed.
 | 
					
						
							|  |  |  | | If the rounding precision is single or double, the ovf_res routine | 
					
						
							|  |  |  | | is needed to correctly supply the max value. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | frcfpnr: | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#6,%d0			|test for forced precision | 
					
						
							|  |  |  | 	beqs	frcfpn_fpcr | 
					
						
							|  |  |  | 	btstl	#2,%d0			|check for double | 
					
						
							|  |  |  | 	bnes	frcfpn_dbl | 
					
						
							|  |  |  | 	movel	#0x1,%d0			|inst is forced single | 
					
						
							|  |  |  | 	bras	frcfpn_rnd | 
					
						
							|  |  |  | frcfpn_dbl: | 
					
						
							|  |  |  | 	movel	#0x2,%d0			|inst is forced double | 
					
						
							|  |  |  | 	bras	frcfpn_rnd | 
					
						
							|  |  |  | frcfpn_fpcr: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
					
						
							|  |  |  | 	tstb	%d0 | 
					
						
							|  |  |  | 	beqs	frcfpn			|if extended, write what you got | 
					
						
							|  |  |  | frcfpn_rnd: | 
					
						
							|  |  |  | 	bclrb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	sne	WBTEMP_SGN(%a6) | 
					
						
							|  |  |  | 	bsrl	ovf_res			|get correct result based on | 
					
						
							|  |  |  | |					;round precision/mode.  This
 | 
					
						
							|  |  |  | |					;sets FPSR_CC correctly
 | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
					
						
							|  |  |  | 	beqs	frcfpn_clr | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | frcfpn_clr: | 
					
						
							|  |  |  | 	orl	#ovfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Perform the write. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | frcfpn: | 
					
						
							|  |  |  | 	bfextu	CMDREG1B(%a6){#6:#3},%d0	|extract fp destination register | 
					
						
							|  |  |  | 	cmpib	#3,%d0 | 
					
						
							|  |  |  | 	bles	frc0123			|check if dest is fp0-fp3 | 
					
						
							|  |  |  | 	movel	#7,%d1 | 
					
						
							|  |  |  | 	subl	%d0,%d1 | 
					
						
							|  |  |  | 	clrl	%d0 | 
					
						
							|  |  |  | 	bsetl	%d1,%d0 | 
					
						
							|  |  |  | 	fmovemx WBTEMP(%a6),%d0 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | frc0123: | 
					
						
							|  |  |  | 	cmpib	#0,%d0 | 
					
						
							|  |  |  | 	beqs	frc0_dst | 
					
						
							|  |  |  | 	cmpib	#1,%d0 | 
					
						
							|  |  |  | 	beqs	frc1_dst | 
					
						
							|  |  |  | 	cmpib	#2,%d0 | 
					
						
							|  |  |  | 	beqs	frc2_dst | 
					
						
							|  |  |  | frc3_dst: | 
					
						
							|  |  |  | 	movel	WBTEMP_EX(%a6),USER_FP3(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_HI(%a6),USER_FP3+4(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_LO(%a6),USER_FP3+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | frc2_dst: | 
					
						
							|  |  |  | 	movel	WBTEMP_EX(%a6),USER_FP2(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_HI(%a6),USER_FP2+4(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_LO(%a6),USER_FP2+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | frc1_dst: | 
					
						
							|  |  |  | 	movel	WBTEMP_EX(%a6),USER_FP1(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_HI(%a6),USER_FP1+4(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_LO(%a6),USER_FP1+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | frc0_dst: | 
					
						
							|  |  |  | 	movel	WBTEMP_EX(%a6),USER_FP0(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_HI(%a6),USER_FP0+4(%a6) | 
					
						
							|  |  |  | 	movel	WBTEMP_LO(%a6),USER_FP0+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Write etemp to fpn. | 
					
						
							|  |  |  | | A check is made on enabled and signalled snan exceptions, | 
					
						
							|  |  |  | | and the destination is not overwritten if this condition exists. | 
					
						
							|  |  |  | | This code is designed to make fmoveins of unsupported data types | 
					
						
							|  |  |  | | faster. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | wr_etemp: | 
					
						
							|  |  |  | 	btstb	#snan_bit,FPSR_EXCEPT(%a6)	|if snan is set, and | 
					
						
							|  |  |  | 	beqs	fmoveinc		|enabled, force restore | 
					
						
							|  |  |  | 	btstb	#snan_bit,FPCR_ENABLE(%a6) |and don't overwrite | 
					
						
							|  |  |  | 	beqs	fmoveinc		|the dest | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
					
						
							|  |  |  | |						;snan handler
 | 
					
						
							|  |  |  | 	tstb	ETEMP(%a6)		|check for negative | 
					
						
							|  |  |  | 	blts	snan_neg | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | snan_neg: | 
					
						
							|  |  |  | 	orl	#neg_bit,USER_FPSR(%a6)	|snan is negative; set N
 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | fmoveinc: | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 	moveb	STAG(%a6),%d0		|check if stag is inf | 
					
						
							|  |  |  | 	andib	#0xe0,%d0 | 
					
						
							|  |  |  | 	cmpib	#0x40,%d0 | 
					
						
							|  |  |  | 	bnes	fminc_cnan | 
					
						
							|  |  |  | 	orl	#inf_mask,USER_FPSR(%a6) |if inf, nothing yet has set I | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|check sign | 
					
						
							|  |  |  | 	bges	fminc_con | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	fminc_con | 
					
						
							|  |  |  | fminc_cnan: | 
					
						
							|  |  |  | 	cmpib	#0x60,%d0			|check if stag is NaN | 
					
						
							|  |  |  | 	bnes	fminc_czero | 
					
						
							|  |  |  | 	orl	#nan_mask,USER_FPSR(%a6) |if nan, nothing yet has set NaN | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
					
						
							|  |  |  | |						;snan handler
 | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|check sign | 
					
						
							|  |  |  | 	bges	fminc_con | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	fminc_con | 
					
						
							|  |  |  | fminc_czero: | 
					
						
							|  |  |  | 	cmpib	#0x20,%d0			|check if zero | 
					
						
							|  |  |  | 	bnes	fminc_con | 
					
						
							|  |  |  | 	orl	#z_mask,USER_FPSR(%a6)	|if zero, set Z | 
					
						
							|  |  |  | 	tstw	LOCAL_EX(%a0)		|check sign | 
					
						
							|  |  |  | 	bges	fminc_con | 
					
						
							|  |  |  | 	orl	#neg_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | fminc_con: | 
					
						
							|  |  |  | 	bfextu	CMDREG1B(%a6){#6:#3},%d0	|extract fp destination register | 
					
						
							|  |  |  | 	cmpib	#3,%d0 | 
					
						
							|  |  |  | 	bles	fp0123			|check if dest is fp0-fp3 | 
					
						
							|  |  |  | 	movel	#7,%d1 | 
					
						
							|  |  |  | 	subl	%d0,%d1 | 
					
						
							|  |  |  | 	clrl	%d0 | 
					
						
							|  |  |  | 	bsetl	%d1,%d0 | 
					
						
							|  |  |  | 	fmovemx ETEMP(%a6),%d0 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fp0123: | 
					
						
							|  |  |  | 	cmpib	#0,%d0 | 
					
						
							|  |  |  | 	beqs	fp0_dst | 
					
						
							|  |  |  | 	cmpib	#1,%d0 | 
					
						
							|  |  |  | 	beqs	fp1_dst | 
					
						
							|  |  |  | 	cmpib	#2,%d0 | 
					
						
							|  |  |  | 	beqs	fp2_dst | 
					
						
							|  |  |  | fp3_dst: | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),USER_FP3(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),USER_FP3+4(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),USER_FP3+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | fp2_dst: | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),USER_FP2(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),USER_FP2+4(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),USER_FP2+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | fp1_dst: | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),USER_FP1(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),USER_FP1+4(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),USER_FP1+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | fp0_dst: | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),USER_FP0(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),USER_FP0+4(%a6) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),USER_FP0+8(%a6) | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | opclass3: | 
					
						
							|  |  |  | 	st	CU_ONLY(%a6) | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0	|check if packed moveout | 
					
						
							|  |  |  | 	andiw	#0x0c00,%d0	|isolate last 2 bits of size field | 
					
						
							|  |  |  | 	cmpiw	#0x0c00,%d0	|if size is 011 or 111, it is packed | 
					
						
							|  |  |  | 	beq	pack_out	|else it is norm or denorm | 
					
						
							|  |  |  | 	bra	mv_out | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |	MOVE OUT | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | mv_tbl: | 
					
						
							|  |  |  | 	.long	li
 | 
					
						
							|  |  |  | 	.long	sgp
 | 
					
						
							|  |  |  | 	.long	xp
 | 
					
						
							|  |  |  | 	.long	mvout_end	|should never be taken | 
					
						
							|  |  |  | 	.long	wi
 | 
					
						
							|  |  |  | 	.long	dp
 | 
					
						
							|  |  |  | 	.long	bi
 | 
					
						
							|  |  |  | 	.long	mvout_end	|should never be taken | 
					
						
							|  |  |  | mv_out: | 
					
						
							|  |  |  | 	bfextu	CMDREG1B(%a6){#3:#3},%d1	|put source specifier in d1 | 
					
						
							|  |  |  | 	leal	mv_tbl,%a0 | 
					
						
							|  |  |  | 	movel	%a0@(%d1:l:4),%a0
 | 
					
						
							|  |  |  | 	jmp	(%a0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This exit is for move-out to memory.  The aunfl bit is | 
					
						
							|  |  |  | | set if the result is inex and unfl is signalled. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | mvout_end: | 
					
						
							|  |  |  | 	btstb	#inex2_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	beqs	no_aufl | 
					
						
							|  |  |  | 	btstb	#unfl_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	beqs	no_aufl | 
					
						
							|  |  |  | 	bsetb	#aunfl_bit,FPSR_AEXCEPT(%a6) | 
					
						
							|  |  |  | no_aufl: | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 	fmovel	#0,%FPSR			|clear any cc bits from res_func | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Return ETEMP to extended format from internal extended format so | 
					
						
							|  |  |  | | that gen_except will have a correctly signed value for ovfl/unfl | 
					
						
							|  |  |  | | handlers. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	bfclr	ETEMP_SGN(%a6){#0:#8} | 
					
						
							|  |  |  | 	beqs	mvout_con | 
					
						
							|  |  |  | 	bsetb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | mvout_con: | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This exit is for move-out to int register.  The aunfl bit is | 
					
						
							|  |  |  | | not set in any case for this move. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | mvouti_end: | 
					
						
							|  |  |  | 	clrw	NMNEXC(%a6) | 
					
						
							|  |  |  | 	bclrb	#E1,E_BYTE(%a6) | 
					
						
							|  |  |  | 	fmovel	#0,%FPSR			|clear any cc bits from res_func | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Return ETEMP to extended format from internal extended format so | 
					
						
							|  |  |  | | that gen_except will have a correctly signed value for ovfl/unfl | 
					
						
							|  |  |  | | handlers. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	bfclr	ETEMP_SGN(%a6){#0:#8} | 
					
						
							|  |  |  | 	beqs	mvouti_con | 
					
						
							|  |  |  | 	bsetb	#sign_bit,ETEMP_EX(%a6) | 
					
						
							|  |  |  | mvouti_con: | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | li is used to handle a long integer source specifier | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | li: | 
					
						
							|  |  |  | 	moveql	#4,%d0		|set byte count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	int_dnrm	|if so, branch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmovemx ETEMP(%a6),%fp0-%fp0 | 
					
						
							|  |  |  | 	fcmpd	#0x41dfffffffc00000,%fp0 | 
					
						
							|  |  |  | | 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec | 
					
						
							|  |  |  | 	fbge	lo_plrg | 
					
						
							|  |  |  | 	fcmpd	#0xc1e0000000000000,%fp0 | 
					
						
							|  |  |  | | c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec | 
					
						
							|  |  |  | 	fble	lo_nlrg | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | at this point, the answer is between the largest pos and neg values | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
					
						
							|  |  |  | 	andil	#0x30,%d1 | 
					
						
							|  |  |  | 	fmovel	%d1,%fpcr | 
					
						
							|  |  |  | 	fmovel	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
					
						
							|  |  |  | 	fmovel %fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
					
						
							|  |  |  | 	bra	int_wrt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lo_plrg: | 
					
						
							|  |  |  | 	movel	#0x7fffffff,L_SCR1(%a6)	|answer is largest positive int | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmpd	#0x41dfffffffe00000,%fp0 | 
					
						
							|  |  |  | | 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec | 
					
						
							|  |  |  | 	fbge	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lo_nlrg: | 
					
						
							|  |  |  | 	movel	#0x80000000,L_SCR1(%a6) | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmpd	#0xc1e0000000100000,%fp0 | 
					
						
							|  |  |  | | c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec | 
					
						
							|  |  |  | 	fblt	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | wi is used to handle a word integer source specifier | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wi: | 
					
						
							|  |  |  | 	moveql	#2,%d0		|set byte count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	int_dnrm	|branch if so | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmovemx ETEMP(%a6),%fp0-%fp0 | 
					
						
							|  |  |  | 	fcmps	#0x46fffe00,%fp0 | 
					
						
							|  |  |  | | 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec | 
					
						
							|  |  |  | 	fbge	wo_plrg | 
					
						
							|  |  |  | 	fcmps	#0xc7000000,%fp0 | 
					
						
							|  |  |  | | c7000000 in sgl prec = c00e00008000000000000000 in ext prec | 
					
						
							|  |  |  | 	fble	wo_nlrg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | at this point, the answer is between the largest pos and neg values | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
					
						
							|  |  |  | 	andil	#0x30,%d1 | 
					
						
							|  |  |  | 	fmovel	%d1,%fpcr | 
					
						
							|  |  |  | 	fmovew	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
					
						
							|  |  |  | 	fmovel %fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
					
						
							|  |  |  | 	bra	int_wrt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wo_plrg: | 
					
						
							|  |  |  | 	movew	#0x7fff,L_SCR1(%a6)	|answer is largest positive int | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmps	#0x46ffff00,%fp0 | 
					
						
							|  |  |  | | 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec | 
					
						
							|  |  |  | 	fbge	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wo_nlrg: | 
					
						
							|  |  |  | 	movew	#0x8000,L_SCR1(%a6) | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmps	#0xc7000080,%fp0 | 
					
						
							|  |  |  | | c7000080 in sgl prec = c00e00008000800000000000 in ext prec | 
					
						
							|  |  |  | 	fblt	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | bi is used to handle a byte integer source specifier | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bi: | 
					
						
							|  |  |  | 	moveql	#1,%d0		|set byte count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	int_dnrm	|branch if so | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmovemx ETEMP(%a6),%fp0-%fp0 | 
					
						
							|  |  |  | 	fcmps	#0x42fe0000,%fp0 | 
					
						
							|  |  |  | | 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec | 
					
						
							|  |  |  | 	fbge	by_plrg | 
					
						
							|  |  |  | 	fcmps	#0xc3000000,%fp0 | 
					
						
							|  |  |  | | c3000000 in sgl prec = c00600008000000000000000 in ext prec | 
					
						
							|  |  |  | 	fble	by_nlrg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | at this point, the answer is between the largest pos and neg values | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 	movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
					
						
							|  |  |  | 	andil	#0x30,%d1 | 
					
						
							|  |  |  | 	fmovel	%d1,%fpcr | 
					
						
							|  |  |  | 	fmoveb	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
					
						
							|  |  |  | 	fmovel %fpsr,%d1 | 
					
						
							|  |  |  | 	orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
					
						
							|  |  |  | 	bra	int_wrt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | by_plrg: | 
					
						
							|  |  |  | 	moveb	#0x7f,L_SCR1(%a6)		|answer is largest positive int | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmps	#0x42ff0000,%fp0 | 
					
						
							|  |  |  | | 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec | 
					
						
							|  |  |  | 	fbge	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | by_nlrg: | 
					
						
							|  |  |  | 	moveb	#0x80,L_SCR1(%a6) | 
					
						
							|  |  |  | 	fbeq	int_wrt			|exact answer | 
					
						
							|  |  |  | 	fcmps	#0xc3008000,%fp0 | 
					
						
							|  |  |  | | c3008000 in sgl prec = c00600008080000000000000 in ext prec | 
					
						
							|  |  |  | 	fblt	int_operr		|set operr | 
					
						
							|  |  |  | 	bra	int_inx			|set inexact | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Common integer routines | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | int_drnrm---account for possible nonzero result for round up with positive | 
					
						
							|  |  |  | | operand and round down for negative answer.  In the first case (result = 1) | 
					
						
							|  |  |  | | byte-width (store in d0) of result must be honored.  In the second case, | 
					
						
							|  |  |  | | -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int_dnrm: | 
					
						
							|  |  |  | 	movel	#0,L_SCR1(%a6)	| initialize result to 0 | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1	| d1 is the rounding mode | 
					
						
							|  |  |  | 	cmpb	#2,%d1 | 
					
						
							|  |  |  | 	bmis	int_inx		| if RN or RZ, done | 
					
						
							|  |  |  | 	bnes	int_rp		| if RP, continue below | 
					
						
							|  |  |  | 	tstw	ETEMP(%a6)	| RM: store -1 in L_SCR1 if src is negative | 
					
						
							|  |  |  | 	bpls	int_inx		| otherwise result is 0 | 
					
						
							|  |  |  | 	movel	#-1,L_SCR1(%a6) | 
					
						
							|  |  |  | 	bras	int_inx | 
					
						
							|  |  |  | int_rp: | 
					
						
							|  |  |  | 	tstw	ETEMP(%a6)	| RP: store +1 of proper width in L_SCR1 if | 
					
						
							|  |  |  | |				; source is greater than 0
 | 
					
						
							|  |  |  | 	bmis	int_inx		| otherwise, result is 0 | 
					
						
							|  |  |  | 	lea	L_SCR1(%a6),%a1	| a1 is address of L_SCR1 | 
					
						
							|  |  |  | 	addal	%d0,%a1		| offset by destination width -1 | 
					
						
							|  |  |  | 	subal	#1,%a1 | 
					
						
							|  |  |  | 	bsetb	#0,(%a1)		| set low bit at a1 address | 
					
						
							|  |  |  | int_inx: | 
					
						
							|  |  |  | 	oril	#inx2a_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bras	int_wrt | 
					
						
							|  |  |  | int_operr: | 
					
						
							|  |  |  | 	fmovemx %fp0-%fp0,FPTEMP(%a6)	|FPTEMP must contain the extended | 
					
						
							|  |  |  | |				;precision source that needs to be
 | 
					
						
							|  |  |  | |				;converted to integer this is required
 | 
					
						
							|  |  |  | |				;if the operr exception is enabled.
 | 
					
						
							|  |  |  | |				;set operr/aiop (no inex2 on int ovfl)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	oril	#opaop_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | |				;fall through to perform int_wrt
 | 
					
						
							|  |  |  | int_wrt: | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a1	|load destination address | 
					
						
							|  |  |  | 	tstl	%a1		|check to see if it is a dest register | 
					
						
							|  |  |  | 	beqs	wrt_dn		|write data register | 
					
						
							|  |  |  | 	lea	L_SCR1(%a6),%a0	|point to supervisor source address | 
					
						
							|  |  |  | 	bsrl	mem_write | 
					
						
							|  |  |  | 	bra	mvouti_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wrt_dn: | 
					
						
							|  |  |  | 	movel	%d0,-(%sp)	|d0 currently contains the size to write | 
					
						
							|  |  |  | 	bsrl	get_fline	|get_fline returns Dn in d0 | 
					
						
							|  |  |  | 	andiw	#0x7,%d0		|isolate register | 
					
						
							|  |  |  | 	movel	(%sp)+,%d1	|get size | 
					
						
							|  |  |  | 	cmpil	#4,%d1		|most frequent case | 
					
						
							|  |  |  | 	beqs	sz_long | 
					
						
							|  |  |  | 	cmpil	#2,%d1 | 
					
						
							|  |  |  | 	bnes	sz_con | 
					
						
							|  |  |  | 	orl	#8,%d0		|add 'word' size to register# | 
					
						
							|  |  |  | 	bras	sz_con | 
					
						
							|  |  |  | sz_long: | 
					
						
							|  |  |  | 	orl	#0x10,%d0		|add 'long' size to register# | 
					
						
							|  |  |  | sz_con: | 
					
						
							|  |  |  | 	movel	%d0,%d1		|reg_dest expects size:reg in d1 | 
					
						
							|  |  |  | 	bsrl	reg_dest	|load proper data register | 
					
						
							|  |  |  | 	bra	mvouti_end | 
					
						
							|  |  |  | xp: | 
					
						
							|  |  |  | 	lea	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	xdnrm | 
					
						
							|  |  |  | 	clrl	%d0 | 
					
						
							|  |  |  | 	bras	do_fp		|do normal case | 
					
						
							|  |  |  | sgp: | 
					
						
							|  |  |  | 	lea	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	sp_catas	|branch if so | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d0 | 
					
						
							|  |  |  | 	lea	sp_bnds,%a1 | 
					
						
							|  |  |  | 	cmpw	(%a1),%d0 | 
					
						
							|  |  |  | 	blt	sp_under | 
					
						
							|  |  |  | 	cmpw	2(%a1),%d0 | 
					
						
							|  |  |  | 	bgt	sp_over | 
					
						
							|  |  |  | 	movel	#1,%d0		|set destination format to single | 
					
						
							|  |  |  | 	bras	do_fp		|do normal case | 
					
						
							|  |  |  | dp: | 
					
						
							|  |  |  | 	lea	ETEMP(%a6),%a0 | 
					
						
							|  |  |  | 	bclrb	#sign_bit,LOCAL_EX(%a0) | 
					
						
							|  |  |  | 	sne	LOCAL_SGN(%a0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	btstb	#7,STAG(%a6)	|check for extended denorm | 
					
						
							|  |  |  | 	bne	dp_catas	|branch if so | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movew	LOCAL_EX(%a0),%d0 | 
					
						
							|  |  |  | 	lea	dp_bnds,%a1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmpw	(%a1),%d0 | 
					
						
							|  |  |  | 	blt	dp_under | 
					
						
							|  |  |  | 	cmpw	2(%a1),%d0 | 
					
						
							|  |  |  | 	bgt	dp_over | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#2,%d0		|set destination format to double | 
					
						
							|  |  |  | |				;fall through to do_fp
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | do_fp: | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|rnd mode in d1 | 
					
						
							|  |  |  | 	swap	%d0			|rnd prec in upper word | 
					
						
							|  |  |  | 	addl	%d0,%d1			|d1 has PREC/MODE info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clrl	%d0			|clear g,r,s | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bsrl	round			|round | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1 | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bfextu	CMDREG1B(%a6){#3:#3},%d1	|extract destination format | 
					
						
							|  |  |  | |					;at this point only the dest
 | 
					
						
							|  |  |  | |					;formats sgl, dbl, ext are
 | 
					
						
							|  |  |  | |					;possible
 | 
					
						
							|  |  |  | 	cmpb	#2,%d1 | 
					
						
							|  |  |  | 	bgts	ddbl			|double=5, extended=2, single=1 | 
					
						
							|  |  |  | 	bnes	dsgl | 
					
						
							|  |  |  | |					;fall through to dext
 | 
					
						
							|  |  |  | dext: | 
					
						
							|  |  |  | 	bsrl	dest_ext | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | dsgl: | 
					
						
							|  |  |  | 	bsrl	dest_sgl | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | ddbl: | 
					
						
							|  |  |  | 	bsrl	dest_dbl | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Handle possible denorm or catastrophic underflow cases here | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | xdnrm: | 
					
						
							|  |  |  | 	bsr	set_xop		|initialize WBTEMP | 
					
						
							|  |  |  | 	bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1 | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
					
						
							|  |  |  | 	bsrl	dest_ext	|store to memory | 
					
						
							|  |  |  | 	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sp_under: | 
					
						
							|  |  |  | 	bsetb	#etemp15_bit,STAG(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmpw	4(%a1),%d0 | 
					
						
							|  |  |  | 	blts	sp_catas	|catastrophic underflow case | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#1,%d0		|load in round precision | 
					
						
							|  |  |  | 	movel	#sgl_thresh,%d1	|load in single denorm threshold | 
					
						
							|  |  |  | 	bsrl	dpspdnrm	|expects d1 to have the proper | 
					
						
							|  |  |  | |				;denorm threshold
 | 
					
						
							|  |  |  | 	bsrl	dest_sgl	|stores value to destination | 
					
						
							|  |  |  | 	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end	|exit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dp_under: | 
					
						
							|  |  |  | 	bsetb	#etemp15_bit,STAG(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmpw	4(%a1),%d0 | 
					
						
							|  |  |  | 	blts	dp_catas	|catastrophic underflow case | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#dbl_thresh,%d1	|load in double precision threshold | 
					
						
							|  |  |  | 	movel	#2,%d0 | 
					
						
							|  |  |  | 	bsrl	dpspdnrm	|expects d1 to have proper | 
					
						
							|  |  |  | |				;denorm threshold
 | 
					
						
							|  |  |  | |				;expects d0 to have round precision
 | 
					
						
							|  |  |  | 	bsrl	dest_dbl	|store value to destination | 
					
						
							|  |  |  | 	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end	|exit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Handle catastrophic underflow cases here | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | sp_catas: | 
					
						
							|  |  |  | | Temp fix for z bit set in unf_sub | 
					
						
							|  |  |  | 	movel	USER_FPSR(%a6),-(%a7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#1,%d0		|set round precision to sgl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bsrl	unf_sub		|a0 points to result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	(%a7)+,USER_FPSR(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#1,%d0 | 
					
						
							|  |  |  | 	subw	%d0,LOCAL_EX(%a0) |account for difference between | 
					
						
							|  |  |  | |				;denorm/norm bias
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1		|a1 has the operand input | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bsrl	dest_sgl	|store the result | 
					
						
							|  |  |  | 	oril	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dp_catas: | 
					
						
							|  |  |  | | Temp fix for z bit set in unf_sub | 
					
						
							|  |  |  | 	movel	USER_FPSR(%a6),-(%a7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#2,%d0		|set round precision to dbl | 
					
						
							|  |  |  | 	bsrl	unf_sub		|a0 points to result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	(%a7)+,USER_FPSR(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#1,%d0 | 
					
						
							|  |  |  | 	subw	%d0,LOCAL_EX(%a0) |account for difference between | 
					
						
							|  |  |  | |				;denorm/norm bias
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1		|a1 has the operand input | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bsrl	dest_dbl	|store the result | 
					
						
							|  |  |  | 	oril	#unfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Handle catastrophic overflow cases here | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | sp_over: | 
					
						
							|  |  |  | | Temp fix for z bit set in unf_sub | 
					
						
							|  |  |  | 	movel	USER_FPSR(%a6),-(%a7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#1,%d0 | 
					
						
							|  |  |  | 	leal	FP_SCR1(%a6),%a0	|use FP_SCR1 for creating result | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	bsrl	ovf_res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	(%a7)+,USER_FPSR(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1 | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0 | 
					
						
							|  |  |  | 	bsrl	dest_sgl | 
					
						
							|  |  |  | 	orl	#ovfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dp_over: | 
					
						
							|  |  |  | | Temp fix for z bit set in ovf_res | 
					
						
							|  |  |  | 	movel	USER_FPSR(%a6),-(%a7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	#2,%d0 | 
					
						
							|  |  |  | 	leal	FP_SCR1(%a6),%a0	|use FP_SCR1 for creating result | 
					
						
							|  |  |  | 	movel	ETEMP_EX(%a6),(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_HI(%a6),4(%a0) | 
					
						
							|  |  |  | 	movel	ETEMP_LO(%a6),8(%a0) | 
					
						
							|  |  |  | 	bsrl	ovf_res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	(%a7)+,USER_FPSR(%a6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1 | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0 | 
					
						
							|  |  |  | 	bsrl	dest_dbl | 
					
						
							|  |  |  | 	orl	#ovfinx_mask,USER_FPSR(%a6) | 
					
						
							|  |  |  | 	bra	mvout_end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |	DPSPDNRM | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | This subroutine takes an extended normalized number and denormalizes | 
					
						
							|  |  |  | | it to the given round precision. This subroutine also decrements | 
					
						
							|  |  |  | | the input operand's exponent by 1 to account for the fact that | 
					
						
							|  |  |  | | dest_sgl or dest_dbl expects a normalized number's bias. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Input: a0  points to a normalized number in internal extended format | 
					
						
							|  |  |  | |	 d0  is the round precision (=1 for sgl; =2 for dbl)
 | 
					
						
							|  |  |  | |	 d1  is the single precision or double precision | 
					
						
							|  |  |  | |	     denorm threshold | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Output: (In the format for dest_sgl or dest_dbl) | 
					
						
							|  |  |  | |	 a0   points to the destination | 
					
						
							|  |  |  | |	 a1   points to the operand | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Exceptions: Reports inexact 2 exception by setting USER_FPSR bits | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | dpspdnrm: | 
					
						
							|  |  |  | 	movel	%d0,-(%a7)	|save round precision | 
					
						
							|  |  |  | 	clrl	%d0		|clear initial g,r,s | 
					
						
							|  |  |  | 	bsrl	dnrm_lp		|careful with d0, it's needed by round | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bfextu	FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode | 
					
						
							|  |  |  | 	swap	%d1 | 
					
						
							|  |  |  | 	movew	2(%a7),%d1	|set rounding precision | 
					
						
							|  |  |  | 	swap	%d1		|at this point d1 has PREC/MODE info | 
					
						
							|  |  |  | 	bsrl	round		|round result, sets the inex bit in | 
					
						
							|  |  |  | |				;USER_FPSR if needed
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movew	#1,%d0 | 
					
						
							|  |  |  | 	subw	%d0,LOCAL_EX(%a0) |account for difference in denorm | 
					
						
							|  |  |  | |				;vs norm bias
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	movel	%a0,%a1		|a1 has the operand input | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
					
						
							|  |  |  | 	addw	#4,%a7		|pop stack | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | SET_XOP initialized WBTEMP with the value pointed to by a0 | 
					
						
							|  |  |  | | input: a0 points to input operand in the internal extended format | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | set_xop: | 
					
						
							|  |  |  | 	movel	LOCAL_EX(%a0),WBTEMP_EX(%a6) | 
					
						
							|  |  |  | 	movel	LOCAL_HI(%a0),WBTEMP_HI(%a6) | 
					
						
							|  |  |  | 	movel	LOCAL_LO(%a0),WBTEMP_LO(%a6) | 
					
						
							|  |  |  | 	bfclr	WBTEMP_SGN(%a6){#0:#8} | 
					
						
							|  |  |  | 	beqs	sxop | 
					
						
							|  |  |  | 	bsetb	#sign_bit,WBTEMP_EX(%a6) | 
					
						
							|  |  |  | sxop: | 
					
						
							|  |  |  | 	bfclr	STAG(%a6){#5:#4}	|clear wbtm66,wbtm1,wbtm0,sbit | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |	P_MOVE | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | p_movet: | 
					
						
							|  |  |  | 	.long	p_move
 | 
					
						
							|  |  |  | 	.long	p_movez
 | 
					
						
							|  |  |  | 	.long	p_movei
 | 
					
						
							|  |  |  | 	.long	p_moven
 | 
					
						
							|  |  |  | 	.long	p_move
 | 
					
						
							|  |  |  | p_regd: | 
					
						
							|  |  |  | 	.long	p_dyd0
 | 
					
						
							|  |  |  | 	.long	p_dyd1
 | 
					
						
							|  |  |  | 	.long	p_dyd2
 | 
					
						
							|  |  |  | 	.long	p_dyd3
 | 
					
						
							|  |  |  | 	.long	p_dyd4
 | 
					
						
							|  |  |  | 	.long	p_dyd5
 | 
					
						
							|  |  |  | 	.long	p_dyd6
 | 
					
						
							|  |  |  | 	.long	p_dyd7
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pack_out: | 
					
						
							|  |  |  | 	leal	p_movet,%a0	|load jmp table address | 
					
						
							|  |  |  | 	movew	STAG(%a6),%d0	|get source tag | 
					
						
							|  |  |  | 	bfextu	%d0{#16:#3},%d0	|isolate source bits | 
					
						
							|  |  |  | 	movel	(%a0,%d0.w*4),%a0	|load a0 with routine label for tag | 
					
						
							|  |  |  | 	jmp	(%a0)		|go to the routine | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | p_write: | 
					
						
							|  |  |  | 	movel	#0x0c,%d0	|get byte count | 
					
						
							|  |  |  | 	movel	EXC_EA(%a6),%a1	|get the destination address | 
					
						
							|  |  |  | 	bsr	mem_write	|write the user's destination | 
					
						
							|  |  |  | 	moveb	#0,CU_SAVEPC(%a6) |set the cu save pc to all 0's | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Also note that the dtag must be set to norm here - this is because | 
					
						
							|  |  |  | | the 040 uses the dtag to execute the correct microcode. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  |         bfclr    DTAG(%a6){#0:#3}  |set dtag to norm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | Notes on handling of special case (zero, inf, and nan) inputs: | 
					
						
							|  |  |  | |	1. Operr is not signalled if the k-factor is greater than 18. | 
					
						
							|  |  |  | |	2. Per the manual, status bits are not set. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | p_move: | 
					
						
							|  |  |  | 	movew	CMDREG1B(%a6),%d0 | 
					
						
							|  |  |  | 	btstl	#kfact_bit,%d0	|test for dynamic k-factor | 
					
						
							|  |  |  | 	beqs	statick		|if clear, k-factor is static | 
					
						
							|  |  |  | dynamick: | 
					
						
							|  |  |  | 	bfextu	%d0{#25:#3},%d0	|isolate register for dynamic k-factor | 
					
						
							|  |  |  | 	lea	p_regd,%a0 | 
					
						
							|  |  |  | 	movel	%a0@(%d0:l:4),%a0
 | 
					
						
							|  |  |  | 	jmp	(%a0) | 
					
						
							|  |  |  | statick: | 
					
						
							|  |  |  | 	andiw	#0x007f,%d0	|get k-factor | 
					
						
							|  |  |  | 	bfexts	%d0{#25:#7},%d0	|sign extend d0 for bindec | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
					
						
							|  |  |  | 	bsrl	bindec		|perform the convert; data at a6
 | 
					
						
							|  |  |  | 	leal	FP_SCR1(%a6),%a0	|load a0 with result address | 
					
						
							|  |  |  | 	bral	p_write | 
					
						
							|  |  |  | p_movez: | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
					
						
							|  |  |  | 	clrw	2(%a0)		|clear lower word of exp | 
					
						
							|  |  |  | 	clrl	4(%a0)		|load second lword of ZERO | 
					
						
							|  |  |  | 	clrl	8(%a0)		|load third lword of ZERO | 
					
						
							|  |  |  | 	bra	p_write		|go write results | 
					
						
							|  |  |  | p_movei: | 
					
						
							|  |  |  | 	fmovel	#0,%FPSR		|clear aiop | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
					
						
							|  |  |  | 	clrw	2(%a0)		|clear lower word of exp | 
					
						
							|  |  |  | 	bra	p_write		|go write the result | 
					
						
							|  |  |  | p_moven: | 
					
						
							|  |  |  | 	leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
					
						
							|  |  |  | 	clrw	2(%a0)		|clear lower word of exp | 
					
						
							|  |  |  | 	bra	p_write		|go write the result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | | Routines to read the dynamic k-factor from Dn. | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | p_dyd0: | 
					
						
							|  |  |  | 	movel	USER_D0(%a6),%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd1: | 
					
						
							|  |  |  | 	movel	USER_D1(%a6),%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd2: | 
					
						
							|  |  |  | 	movel	%d2,%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd3: | 
					
						
							|  |  |  | 	movel	%d3,%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd4: | 
					
						
							|  |  |  | 	movel	%d4,%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd5: | 
					
						
							|  |  |  | 	movel	%d5,%d0 | 
					
						
							|  |  |  | 	bras	statick | 
					
						
							|  |  |  | p_dyd6: | 
					
						
							|  |  |  | 	movel	%d6,%d0 | 
					
						
							|  |  |  | 	bra	statick | 
					
						
							|  |  |  | p_dyd7: | 
					
						
							|  |  |  | 	movel	%d7,%d0 | 
					
						
							|  |  |  | 	bra	statick | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	|end |