162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	x_ovfl.sa 3.5 7/1/91
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci|	fpsp_ovfl --- FPSP handler for overflow exception
562306a36Sopenharmony_ci|
662306a36Sopenharmony_ci|	Overflow occurs when a floating-point intermediate result is
762306a36Sopenharmony_ci|	too large to be represented in a floating-point data register,
862306a36Sopenharmony_ci|	or when storing to memory, the contents of a floating-point
962306a36Sopenharmony_ci|	data register are too large to be represented in the
1062306a36Sopenharmony_ci|	destination format.
1162306a36Sopenharmony_ci|
1262306a36Sopenharmony_ci| Trap disabled results
1362306a36Sopenharmony_ci|
1462306a36Sopenharmony_ci| If the instruction is move_out, then garbage is stored in the
1562306a36Sopenharmony_ci| destination.  If the instruction is not move_out, then the
1662306a36Sopenharmony_ci| destination is not affected.  For 68881 compatibility, the
1762306a36Sopenharmony_ci| following values should be stored at the destination, based
1862306a36Sopenharmony_ci| on the current rounding mode:
1962306a36Sopenharmony_ci|
2062306a36Sopenharmony_ci|  RN	Infinity with the sign of the intermediate result.
2162306a36Sopenharmony_ci|  RZ	Largest magnitude number, with the sign of the
2262306a36Sopenharmony_ci|	intermediate result.
2362306a36Sopenharmony_ci|  RM   For pos overflow, the largest pos number. For neg overflow,
2462306a36Sopenharmony_ci|	-infinity
2562306a36Sopenharmony_ci|  RP   For pos overflow, +infinity. For neg overflow, the largest
2662306a36Sopenharmony_ci|	neg number
2762306a36Sopenharmony_ci|
2862306a36Sopenharmony_ci| Trap enabled results
2962306a36Sopenharmony_ci| All trap disabled code applies.  In addition the exceptional
3062306a36Sopenharmony_ci| operand needs to be made available to the users exception handler
3162306a36Sopenharmony_ci| with a bias of $6000 subtracted from the exponent.
3262306a36Sopenharmony_ci|
3362306a36Sopenharmony_ci|
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
3662306a36Sopenharmony_ci|			All Rights Reserved
3762306a36Sopenharmony_ci|
3862306a36Sopenharmony_ci|       For details on the license for this file, please see the
3962306a36Sopenharmony_ci|       file, README, in this same directory.
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciX_OVFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	|section	8
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include "fpsp.h"
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	|xref	ovf_r_x2
4862306a36Sopenharmony_ci	|xref	ovf_r_x3
4962306a36Sopenharmony_ci	|xref	store
5062306a36Sopenharmony_ci	|xref	real_ovfl
5162306a36Sopenharmony_ci	|xref	real_inex
5262306a36Sopenharmony_ci	|xref	fpsp_done
5362306a36Sopenharmony_ci	|xref	g_opcls
5462306a36Sopenharmony_ci	|xref	b1238_fix
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	.global	fpsp_ovfl
5762306a36Sopenharmony_cifpsp_ovfl:
5862306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
5962306a36Sopenharmony_ci	fsave		-(%a7)
6062306a36Sopenharmony_ci	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
6162306a36Sopenharmony_ci	fmovemx	%fp0-%fp3,USER_FP0(%a6)
6262306a36Sopenharmony_ci	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci|
6562306a36Sopenharmony_ci|	The 040 doesn't set the AINEX bit in the FPSR, the following
6662306a36Sopenharmony_ci|	line temporarily rectifies this error.
6762306a36Sopenharmony_ci|
6862306a36Sopenharmony_ci	bsetb	#ainex_bit,FPSR_AEXCEPT(%a6)
6962306a36Sopenharmony_ci|
7062306a36Sopenharmony_ci	bsrl	ovf_adj		|denormalize, round & store interm op
7162306a36Sopenharmony_ci|
7262306a36Sopenharmony_ci|	if overflow traps not enabled check for inexact exception
7362306a36Sopenharmony_ci|
7462306a36Sopenharmony_ci	btstb	#ovfl_bit,FPCR_ENABLE(%a6)
7562306a36Sopenharmony_ci	beqs	ck_inex
7662306a36Sopenharmony_ci|
7762306a36Sopenharmony_ci	btstb		#E3,E_BYTE(%a6)
7862306a36Sopenharmony_ci	beqs		no_e3_1
7962306a36Sopenharmony_ci	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
8062306a36Sopenharmony_ci	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
8162306a36Sopenharmony_ci	bsrl		b1238_fix
8262306a36Sopenharmony_ci	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
8362306a36Sopenharmony_ci	orl		#sx_mask,E_BYTE(%a6)
8462306a36Sopenharmony_cino_e3_1:
8562306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
8662306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
8762306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
8862306a36Sopenharmony_ci	frestore	(%a7)+
8962306a36Sopenharmony_ci	unlk		%a6
9062306a36Sopenharmony_ci	bral		real_ovfl
9162306a36Sopenharmony_ci|
9262306a36Sopenharmony_ci| It is possible to have either inex2 or inex1 exceptions with the
9362306a36Sopenharmony_ci| ovfl.  If the inex enable bit is set in the FPCR, and either
9462306a36Sopenharmony_ci| inex2 or inex1 occurred, we must clean up and branch to the
9562306a36Sopenharmony_ci| real inex handler.
9662306a36Sopenharmony_ci|
9762306a36Sopenharmony_cick_inex:
9862306a36Sopenharmony_ci|	move.b		FPCR_ENABLE(%a6),%d0
9962306a36Sopenharmony_ci|	and.b		FPSR_EXCEPT(%a6),%d0
10062306a36Sopenharmony_ci|	andi.b		#$3,%d0
10162306a36Sopenharmony_ci	btstb		#inex2_bit,FPCR_ENABLE(%a6)
10262306a36Sopenharmony_ci	beqs		ovfl_exit
10362306a36Sopenharmony_ci|
10462306a36Sopenharmony_ci| Inexact enabled and reported, and we must take an inexact exception.
10562306a36Sopenharmony_ci|
10662306a36Sopenharmony_citake_inex:
10762306a36Sopenharmony_ci	btstb		#E3,E_BYTE(%a6)
10862306a36Sopenharmony_ci	beqs		no_e3_2
10962306a36Sopenharmony_ci	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
11062306a36Sopenharmony_ci	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
11162306a36Sopenharmony_ci	bsrl		b1238_fix
11262306a36Sopenharmony_ci	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
11362306a36Sopenharmony_ci	orl		#sx_mask,E_BYTE(%a6)
11462306a36Sopenharmony_cino_e3_2:
11562306a36Sopenharmony_ci	moveb		#INEX_VEC,EXC_VEC+1(%a6)
11662306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
11762306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
11862306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
11962306a36Sopenharmony_ci	frestore	(%a7)+
12062306a36Sopenharmony_ci	unlk		%a6
12162306a36Sopenharmony_ci	bral		real_inex
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciovfl_exit:
12462306a36Sopenharmony_ci	bclrb	#E3,E_BYTE(%a6)	|test and clear E3 bit
12562306a36Sopenharmony_ci	beqs	e1_set
12662306a36Sopenharmony_ci|
12762306a36Sopenharmony_ci| Clear dirty bit on dest resister in the frame before branching
12862306a36Sopenharmony_ci| to b1238_fix.
12962306a36Sopenharmony_ci|
13062306a36Sopenharmony_ci	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
13162306a36Sopenharmony_ci	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
13262306a36Sopenharmony_ci	bsrl		b1238_fix		|test for bug1238 case
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
13562306a36Sopenharmony_ci	orl		#sx_mask,E_BYTE(%a6)
13662306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
13762306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
13862306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
13962306a36Sopenharmony_ci	frestore	(%a7)+
14062306a36Sopenharmony_ci	unlk		%a6
14162306a36Sopenharmony_ci	bral		fpsp_done
14262306a36Sopenharmony_cie1_set:
14362306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
14462306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
14562306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
14662306a36Sopenharmony_ci	unlk		%a6
14762306a36Sopenharmony_ci	bral		fpsp_done
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci|
15062306a36Sopenharmony_ci|	ovf_adj
15162306a36Sopenharmony_ci|
15262306a36Sopenharmony_ciovf_adj:
15362306a36Sopenharmony_ci|
15462306a36Sopenharmony_ci| Have a0 point to the correct operand.
15562306a36Sopenharmony_ci|
15662306a36Sopenharmony_ci	btstb	#E3,E_BYTE(%a6)	|test E3 bit
15762306a36Sopenharmony_ci	beqs	ovf_e1
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	lea	WBTEMP(%a6),%a0
16062306a36Sopenharmony_ci	bras	ovf_com
16162306a36Sopenharmony_ciovf_e1:
16262306a36Sopenharmony_ci	lea	ETEMP(%a6),%a0
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ciovf_com:
16562306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
16662306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	bsrl	g_opcls		|returns opclass in d0
16962306a36Sopenharmony_ci	cmpiw	#3,%d0		|check for opclass3
17062306a36Sopenharmony_ci	bnes	not_opc011
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci|
17362306a36Sopenharmony_ci| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
17462306a36Sopenharmony_ci| CCs are defined to be 'not affected' for the opclass3 instruction.
17562306a36Sopenharmony_ci|
17662306a36Sopenharmony_ci	moveb	FPSR_CC(%a6),L_SCR1(%a6)
17762306a36Sopenharmony_ci	bsrl	ovf_r_x3	|returns a0 pointing to result
17862306a36Sopenharmony_ci	moveb	L_SCR1(%a6),FPSR_CC(%a6)
17962306a36Sopenharmony_ci	bral	store		|stores to memory or register
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cinot_opc011:
18262306a36Sopenharmony_ci	bsrl	ovf_r_x2	|returns a0 pointing to result
18362306a36Sopenharmony_ci	bral	store		|stores to memory or register
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	|end
186