xref: /linux/arch/m68k/fpsp040/x_ovfl.S (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
11da177e4SLinus Torvalds|
21da177e4SLinus Torvalds|	x_ovfl.sa 3.5 7/1/91
31da177e4SLinus Torvalds|
41da177e4SLinus Torvalds|	fpsp_ovfl --- FPSP handler for overflow exception
51da177e4SLinus Torvalds|
61da177e4SLinus Torvalds|	Overflow occurs when a floating-point intermediate result is
71da177e4SLinus Torvalds|	too large to be represented in a floating-point data register,
81da177e4SLinus Torvalds|	or when storing to memory, the contents of a floating-point
91da177e4SLinus Torvalds|	data register are too large to be represented in the
101da177e4SLinus Torvalds|	destination format.
111da177e4SLinus Torvalds|
121da177e4SLinus Torvalds| Trap disabled results
131da177e4SLinus Torvalds|
141da177e4SLinus Torvalds| If the instruction is move_out, then garbage is stored in the
151da177e4SLinus Torvalds| destination.  If the instruction is not move_out, then the
161da177e4SLinus Torvalds| destination is not affected.  For 68881 compatibility, the
171da177e4SLinus Torvalds| following values should be stored at the destination, based
181da177e4SLinus Torvalds| on the current rounding mode:
191da177e4SLinus Torvalds|
201da177e4SLinus Torvalds|  RN	Infinity with the sign of the intermediate result.
211da177e4SLinus Torvalds|  RZ	Largest magnitude number, with the sign of the
221da177e4SLinus Torvalds|	intermediate result.
231da177e4SLinus Torvalds|  RM   For pos overflow, the largest pos number. For neg overflow,
241da177e4SLinus Torvalds|	-infinity
251da177e4SLinus Torvalds|  RP   For pos overflow, +infinity. For neg overflow, the largest
261da177e4SLinus Torvalds|	neg number
271da177e4SLinus Torvalds|
281da177e4SLinus Torvalds| Trap enabled results
291da177e4SLinus Torvalds| All trap disabled code applies.  In addition the exceptional
301da177e4SLinus Torvalds| operand needs to be made available to the users exception handler
311da177e4SLinus Torvalds| with a bias of $6000 subtracted from the exponent.
321da177e4SLinus Torvalds|
331da177e4SLinus Torvalds|
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds|		Copyright (C) Motorola, Inc. 1990
361da177e4SLinus Torvalds|			All Rights Reserved
371da177e4SLinus Torvalds|
38*e00d82d0SMatt Waddel|       For details on the license for this file, please see the
39*e00d82d0SMatt Waddel|       file, README, in this same directory.
401da177e4SLinus Torvalds
411da177e4SLinus TorvaldsX_OVFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds	|section	8
441da177e4SLinus Torvalds
451da177e4SLinus Torvalds#include "fpsp.h"
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds	|xref	ovf_r_x2
481da177e4SLinus Torvalds	|xref	ovf_r_x3
491da177e4SLinus Torvalds	|xref	store
501da177e4SLinus Torvalds	|xref	real_ovfl
511da177e4SLinus Torvalds	|xref	real_inex
521da177e4SLinus Torvalds	|xref	fpsp_done
531da177e4SLinus Torvalds	|xref	g_opcls
541da177e4SLinus Torvalds	|xref	b1238_fix
551da177e4SLinus Torvalds
561da177e4SLinus Torvalds	.global	fpsp_ovfl
571da177e4SLinus Torvaldsfpsp_ovfl:
581da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
591da177e4SLinus Torvalds	fsave		-(%a7)
601da177e4SLinus Torvalds	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
611da177e4SLinus Torvalds	fmovemx	%fp0-%fp3,USER_FP0(%a6)
621da177e4SLinus Torvalds	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds|
651da177e4SLinus Torvalds|	The 040 doesn't set the AINEX bit in the FPSR, the following
661da177e4SLinus Torvalds|	line temporarily rectifies this error.
671da177e4SLinus Torvalds|
681da177e4SLinus Torvalds	bsetb	#ainex_bit,FPSR_AEXCEPT(%a6)
691da177e4SLinus Torvalds|
701da177e4SLinus Torvalds	bsrl	ovf_adj		|denormalize, round & store interm op
711da177e4SLinus Torvalds|
721da177e4SLinus Torvalds|	if overflow traps not enabled check for inexact exception
731da177e4SLinus Torvalds|
741da177e4SLinus Torvalds	btstb	#ovfl_bit,FPCR_ENABLE(%a6)
751da177e4SLinus Torvalds	beqs	ck_inex
761da177e4SLinus Torvalds|
771da177e4SLinus Torvalds	btstb		#E3,E_BYTE(%a6)
781da177e4SLinus Torvalds	beqs		no_e3_1
791da177e4SLinus Torvalds	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
801da177e4SLinus Torvalds	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
811da177e4SLinus Torvalds	bsrl		b1238_fix
821da177e4SLinus Torvalds	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
831da177e4SLinus Torvalds	orl		#sx_mask,E_BYTE(%a6)
841da177e4SLinus Torvaldsno_e3_1:
851da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
861da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
871da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
881da177e4SLinus Torvalds	frestore	(%a7)+
891da177e4SLinus Torvalds	unlk		%a6
901da177e4SLinus Torvalds	bral		real_ovfl
911da177e4SLinus Torvalds|
921da177e4SLinus Torvalds| It is possible to have either inex2 or inex1 exceptions with the
931da177e4SLinus Torvalds| ovfl.  If the inex enable bit is set in the FPCR, and either
941da177e4SLinus Torvalds| inex2 or inex1 occurred, we must clean up and branch to the
951da177e4SLinus Torvalds| real inex handler.
961da177e4SLinus Torvalds|
971da177e4SLinus Torvaldsck_inex:
981da177e4SLinus Torvalds|	move.b		FPCR_ENABLE(%a6),%d0
991da177e4SLinus Torvalds|	and.b		FPSR_EXCEPT(%a6),%d0
1001da177e4SLinus Torvalds|	andi.b		#$3,%d0
1011da177e4SLinus Torvalds	btstb		#inex2_bit,FPCR_ENABLE(%a6)
1021da177e4SLinus Torvalds	beqs		ovfl_exit
1031da177e4SLinus Torvalds|
1041da177e4SLinus Torvalds| Inexact enabled and reported, and we must take an inexact exception.
1051da177e4SLinus Torvalds|
1061da177e4SLinus Torvaldstake_inex:
1071da177e4SLinus Torvalds	btstb		#E3,E_BYTE(%a6)
1081da177e4SLinus Torvalds	beqs		no_e3_2
1091da177e4SLinus Torvalds	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
1101da177e4SLinus Torvalds	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
1111da177e4SLinus Torvalds	bsrl		b1238_fix
1121da177e4SLinus Torvalds	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
1131da177e4SLinus Torvalds	orl		#sx_mask,E_BYTE(%a6)
1141da177e4SLinus Torvaldsno_e3_2:
1151da177e4SLinus Torvalds	moveb		#INEX_VEC,EXC_VEC+1(%a6)
1161da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
1171da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
1181da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
1191da177e4SLinus Torvalds	frestore	(%a7)+
1201da177e4SLinus Torvalds	unlk		%a6
1211da177e4SLinus Torvalds	bral		real_inex
1221da177e4SLinus Torvalds
1231da177e4SLinus Torvaldsovfl_exit:
1241da177e4SLinus Torvalds	bclrb	#E3,E_BYTE(%a6)	|test and clear E3 bit
1251da177e4SLinus Torvalds	beqs	e1_set
1261da177e4SLinus Torvalds|
1271da177e4SLinus Torvalds| Clear dirty bit on dest resister in the frame before branching
1281da177e4SLinus Torvalds| to b1238_fix.
1291da177e4SLinus Torvalds|
1301da177e4SLinus Torvalds	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
1311da177e4SLinus Torvalds	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
1321da177e4SLinus Torvalds	bsrl		b1238_fix		|test for bug1238 case
1331da177e4SLinus Torvalds
1341da177e4SLinus Torvalds	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
1351da177e4SLinus Torvalds	orl		#sx_mask,E_BYTE(%a6)
1361da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
1371da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
1381da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
1391da177e4SLinus Torvalds	frestore	(%a7)+
1401da177e4SLinus Torvalds	unlk		%a6
1411da177e4SLinus Torvalds	bral		fpsp_done
1421da177e4SLinus Torvaldse1_set:
1431da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
1441da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
1451da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
1461da177e4SLinus Torvalds	unlk		%a6
1471da177e4SLinus Torvalds	bral		fpsp_done
1481da177e4SLinus Torvalds
1491da177e4SLinus Torvalds|
1501da177e4SLinus Torvalds|	ovf_adj
1511da177e4SLinus Torvalds|
1521da177e4SLinus Torvaldsovf_adj:
1531da177e4SLinus Torvalds|
1541da177e4SLinus Torvalds| Have a0 point to the correct operand.
1551da177e4SLinus Torvalds|
1561da177e4SLinus Torvalds	btstb	#E3,E_BYTE(%a6)	|test E3 bit
1571da177e4SLinus Torvalds	beqs	ovf_e1
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds	lea	WBTEMP(%a6),%a0
1601da177e4SLinus Torvalds	bras	ovf_com
1611da177e4SLinus Torvaldsovf_e1:
1621da177e4SLinus Torvalds	lea	ETEMP(%a6),%a0
1631da177e4SLinus Torvalds
1641da177e4SLinus Torvaldsovf_com:
1651da177e4SLinus Torvalds	bclrb	#sign_bit,LOCAL_EX(%a0)
1661da177e4SLinus Torvalds	sne	LOCAL_SGN(%a0)
1671da177e4SLinus Torvalds
1681da177e4SLinus Torvalds	bsrl	g_opcls		|returns opclass in d0
1691da177e4SLinus Torvalds	cmpiw	#3,%d0		|check for opclass3
1701da177e4SLinus Torvalds	bnes	not_opc011
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds|
1731da177e4SLinus Torvalds| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
1741da177e4SLinus Torvalds| CCs are defined to be 'not affected' for the opclass3 instruction.
1751da177e4SLinus Torvalds|
1761da177e4SLinus Torvalds	moveb	FPSR_CC(%a6),L_SCR1(%a6)
1771da177e4SLinus Torvalds	bsrl	ovf_r_x3	|returns a0 pointing to result
1781da177e4SLinus Torvalds	moveb	L_SCR1(%a6),FPSR_CC(%a6)
1791da177e4SLinus Torvalds	bral	store		|stores to memory or register
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvaldsnot_opc011:
1821da177e4SLinus Torvalds	bsrl	ovf_r_x2	|returns a0 pointing to result
1831da177e4SLinus Torvalds	bral	store		|stores to memory or register
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds	|end
186