186 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|
 | 
						|
|	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
 | 
						|
|
 | 
						|
|       For details on the license for this file, please see the
 | 
						|
|       file, README, in this same directory.
 | 
						|
 | 
						|
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 occurred, 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
 |