patch-1.3.94 linux/arch/m68k/fpsp040/x_ovfl.S

Next file: linux/arch/m68k/fpsp040/x_snan.S
Previous file: linux/arch/m68k/fpsp040/x_operr.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.93/linux/arch/m68k/fpsp040/x_ovfl.S linux/arch/m68k/fpsp040/x_ovfl.S
@@ -0,0 +1,186 @@
+|
+|	x_ovfl.sa 3.5 7/1/91
+|
+|	fpsp_ovfl --- FPSP handler for overflow exception
+|
+|	Overflow occurs when a floating-point intermediate result is
+|	too large to be represented in a floating-point data register,
+|	or when storing to memory, the contents of a floating-point
+|	data register are too large to be represented in the
+|	destination format.
+|		
+| Trap disabled results
+|
+| If the instruction is move_out, then garbage is stored in the
+| destination.  If the instruction is not move_out, then the
+| destination is not affected.  For 68881 compatibility, the
+| following values should be stored at the destination, based
+| on the current rounding mode:
+|
+|  RN	Infinity with the sign of the intermediate result.
+|  RZ	Largest magnitude number, with the sign of the
+|	intermediate result.
+|  RM   For pos overflow, the largest pos number. For neg overflow,
+|	-infinity
+|  RP   For pos overflow, +infinity. For neg overflow, the largest
+|	neg number
+|
+| Trap enabled results
+| All trap disabled code applies.  In addition the exceptional
+| operand needs to be made available to the users exception handler
+| with a bias of $6000 subtracted from the exponent.
+|
+|
+
+|		Copyright (C) Motorola, Inc. 1990
+|			All Rights Reserved
+|
+|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
+|	The copyright notice above does not evidence any  
+|	actual or intended publication of such source code.
+
+X_OVFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
+
+	|section	8
+
+	.include "fpsp.h"
+
+	|xref	ovf_r_x2
+	|xref	ovf_r_x3
+	|xref	store
+	|xref	real_ovfl
+	|xref	real_inex
+	|xref	fpsp_done
+	|xref	g_opcls
+	|xref	b1238_fix
+
+	.global	fpsp_ovfl
+fpsp_ovfl:
+	link		%a6,#-LOCAL_SIZE
+	fsave		-(%a7)
+	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
+	fmovemx	%fp0-%fp3,USER_FP0(%a6)
+	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
+
+|
+|	The 040 doesn't set the AINEX bit in the FPSR, the following
+|	line temporarily rectifies this error.
+|
+	bsetb	#ainex_bit,FPSR_AEXCEPT(%a6)
+|
+	bsrl	ovf_adj		|denormalize, round & store interm op
+|
+|	if overflow traps not enabled check for inexact exception
+|
+	btstb	#ovfl_bit,FPCR_ENABLE(%a6)
+	beqs	ck_inex	
+|
+	btstb		#E3,E_BYTE(%a6)
+	beqs		no_e3_1
+	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
+	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
+	bsrl		b1238_fix
+	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
+	orl		#sx_mask,E_BYTE(%a6)
+no_e3_1:
+	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
+	fmovemx	USER_FP0(%a6),%fp0-%fp3
+	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+	frestore	(%a7)+
+	unlk		%a6
+	bral		real_ovfl
+|
+| It is possible to have either inex2 or inex1 exceptions with the
+| ovfl.  If the inex enable bit is set in the FPCR, and either
+| inex2 or inex1 occured, we must clean up and branch to the
+| real inex handler.
+|
+ck_inex:
+|	move.b		FPCR_ENABLE(%a6),%d0
+|	and.b		FPSR_EXCEPT(%a6),%d0
+|	andi.b		#$3,%d0
+	btstb		#inex2_bit,FPCR_ENABLE(%a6)
+	beqs		ovfl_exit
+|
+| Inexact enabled and reported, and we must take an inexact exception.
+|
+take_inex:
+	btstb		#E3,E_BYTE(%a6)
+	beqs		no_e3_2
+	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
+	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
+	bsrl		b1238_fix
+	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
+	orl		#sx_mask,E_BYTE(%a6)
+no_e3_2:
+	moveb		#INEX_VEC,EXC_VEC+1(%a6)
+	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
+	fmovemx	USER_FP0(%a6),%fp0-%fp3
+	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+	frestore	(%a7)+
+	unlk		%a6
+	bral		real_inex
+	
+ovfl_exit:
+	bclrb	#E3,E_BYTE(%a6)	|test and clear E3 bit
+	beqs	e1_set
+|
+| Clear dirty bit on dest resister in the frame before branching
+| to b1238_fix.
+|
+	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
+	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
+	bsrl		b1238_fix		|test for bug1238 case
+
+	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
+	orl		#sx_mask,E_BYTE(%a6)
+	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
+	fmovemx	USER_FP0(%a6),%fp0-%fp3
+	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+	frestore	(%a7)+
+	unlk		%a6
+	bral		fpsp_done
+e1_set:
+	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
+	fmovemx	USER_FP0(%a6),%fp0-%fp3
+	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+	unlk		%a6
+	bral		fpsp_done
+
+|
+|	ovf_adj
+|
+ovf_adj:
+|
+| Have a0 point to the correct operand. 
+|
+	btstb	#E3,E_BYTE(%a6)	|test E3 bit
+	beqs	ovf_e1
+
+	lea	WBTEMP(%a6),%a0
+	bras	ovf_com
+ovf_e1:
+	lea	ETEMP(%a6),%a0
+
+ovf_com:
+	bclrb	#sign_bit,LOCAL_EX(%a0)
+	sne	LOCAL_SGN(%a0)
+
+	bsrl	g_opcls		|returns opclass in d0
+	cmpiw	#3,%d0		|check for opclass3
+	bnes	not_opc011
+
+|
+| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
+| CCs are defined to be 'not affected' for the opclass3 instruction.
+|
+	moveb	FPSR_CC(%a6),L_SCR1(%a6)
+ 	bsrl	ovf_r_x3	|returns a0 pointing to result
+	moveb	L_SCR1(%a6),FPSR_CC(%a6)
+	bral	store		|stores to memory or register
+	
+not_opc011:
+	bsrl	ovf_r_x2	|returns a0 pointing to result
+	bral	store		|stores to memory or register
+
+	|end

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this