xref: /OK3568_Linux_fs/kernel/arch/m68k/fpsp040/x_ovfl.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun|
2*4882a593Smuzhiyun|	x_ovfl.sa 3.5 7/1/91
3*4882a593Smuzhiyun|
4*4882a593Smuzhiyun|	fpsp_ovfl --- FPSP handler for overflow exception
5*4882a593Smuzhiyun|
6*4882a593Smuzhiyun|	Overflow occurs when a floating-point intermediate result is
7*4882a593Smuzhiyun|	too large to be represented in a floating-point data register,
8*4882a593Smuzhiyun|	or when storing to memory, the contents of a floating-point
9*4882a593Smuzhiyun|	data register are too large to be represented in the
10*4882a593Smuzhiyun|	destination format.
11*4882a593Smuzhiyun|
12*4882a593Smuzhiyun| Trap disabled results
13*4882a593Smuzhiyun|
14*4882a593Smuzhiyun| If the instruction is move_out, then garbage is stored in the
15*4882a593Smuzhiyun| destination.  If the instruction is not move_out, then the
16*4882a593Smuzhiyun| destination is not affected.  For 68881 compatibility, the
17*4882a593Smuzhiyun| following values should be stored at the destination, based
18*4882a593Smuzhiyun| on the current rounding mode:
19*4882a593Smuzhiyun|
20*4882a593Smuzhiyun|  RN	Infinity with the sign of the intermediate result.
21*4882a593Smuzhiyun|  RZ	Largest magnitude number, with the sign of the
22*4882a593Smuzhiyun|	intermediate result.
23*4882a593Smuzhiyun|  RM   For pos overflow, the largest pos number. For neg overflow,
24*4882a593Smuzhiyun|	-infinity
25*4882a593Smuzhiyun|  RP   For pos overflow, +infinity. For neg overflow, the largest
26*4882a593Smuzhiyun|	neg number
27*4882a593Smuzhiyun|
28*4882a593Smuzhiyun| Trap enabled results
29*4882a593Smuzhiyun| All trap disabled code applies.  In addition the exceptional
30*4882a593Smuzhiyun| operand needs to be made available to the users exception handler
31*4882a593Smuzhiyun| with a bias of $6000 subtracted from the exponent.
32*4882a593Smuzhiyun|
33*4882a593Smuzhiyun|
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun|		Copyright (C) Motorola, Inc. 1990
36*4882a593Smuzhiyun|			All Rights Reserved
37*4882a593Smuzhiyun|
38*4882a593Smuzhiyun|       For details on the license for this file, please see the
39*4882a593Smuzhiyun|       file, README, in this same directory.
40*4882a593Smuzhiyun
41*4882a593SmuzhiyunX_OVFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun	|section	8
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun#include "fpsp.h"
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun	|xref	ovf_r_x2
48*4882a593Smuzhiyun	|xref	ovf_r_x3
49*4882a593Smuzhiyun	|xref	store
50*4882a593Smuzhiyun	|xref	real_ovfl
51*4882a593Smuzhiyun	|xref	real_inex
52*4882a593Smuzhiyun	|xref	fpsp_done
53*4882a593Smuzhiyun	|xref	g_opcls
54*4882a593Smuzhiyun	|xref	b1238_fix
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun	.global	fpsp_ovfl
57*4882a593Smuzhiyunfpsp_ovfl:
58*4882a593Smuzhiyun	link		%a6,#-LOCAL_SIZE
59*4882a593Smuzhiyun	fsave		-(%a7)
60*4882a593Smuzhiyun	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
61*4882a593Smuzhiyun	fmovemx	%fp0-%fp3,USER_FP0(%a6)
62*4882a593Smuzhiyun	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun|
65*4882a593Smuzhiyun|	The 040 doesn't set the AINEX bit in the FPSR, the following
66*4882a593Smuzhiyun|	line temporarily rectifies this error.
67*4882a593Smuzhiyun|
68*4882a593Smuzhiyun	bsetb	#ainex_bit,FPSR_AEXCEPT(%a6)
69*4882a593Smuzhiyun|
70*4882a593Smuzhiyun	bsrl	ovf_adj		|denormalize, round & store interm op
71*4882a593Smuzhiyun|
72*4882a593Smuzhiyun|	if overflow traps not enabled check for inexact exception
73*4882a593Smuzhiyun|
74*4882a593Smuzhiyun	btstb	#ovfl_bit,FPCR_ENABLE(%a6)
75*4882a593Smuzhiyun	beqs	ck_inex
76*4882a593Smuzhiyun|
77*4882a593Smuzhiyun	btstb		#E3,E_BYTE(%a6)
78*4882a593Smuzhiyun	beqs		no_e3_1
79*4882a593Smuzhiyun	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
80*4882a593Smuzhiyun	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
81*4882a593Smuzhiyun	bsrl		b1238_fix
82*4882a593Smuzhiyun	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
83*4882a593Smuzhiyun	orl		#sx_mask,E_BYTE(%a6)
84*4882a593Smuzhiyunno_e3_1:
85*4882a593Smuzhiyun	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
86*4882a593Smuzhiyun	fmovemx	USER_FP0(%a6),%fp0-%fp3
87*4882a593Smuzhiyun	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
88*4882a593Smuzhiyun	frestore	(%a7)+
89*4882a593Smuzhiyun	unlk		%a6
90*4882a593Smuzhiyun	bral		real_ovfl
91*4882a593Smuzhiyun|
92*4882a593Smuzhiyun| It is possible to have either inex2 or inex1 exceptions with the
93*4882a593Smuzhiyun| ovfl.  If the inex enable bit is set in the FPCR, and either
94*4882a593Smuzhiyun| inex2 or inex1 occurred, we must clean up and branch to the
95*4882a593Smuzhiyun| real inex handler.
96*4882a593Smuzhiyun|
97*4882a593Smuzhiyunck_inex:
98*4882a593Smuzhiyun|	move.b		FPCR_ENABLE(%a6),%d0
99*4882a593Smuzhiyun|	and.b		FPSR_EXCEPT(%a6),%d0
100*4882a593Smuzhiyun|	andi.b		#$3,%d0
101*4882a593Smuzhiyun	btstb		#inex2_bit,FPCR_ENABLE(%a6)
102*4882a593Smuzhiyun	beqs		ovfl_exit
103*4882a593Smuzhiyun|
104*4882a593Smuzhiyun| Inexact enabled and reported, and we must take an inexact exception.
105*4882a593Smuzhiyun|
106*4882a593Smuzhiyuntake_inex:
107*4882a593Smuzhiyun	btstb		#E3,E_BYTE(%a6)
108*4882a593Smuzhiyun	beqs		no_e3_2
109*4882a593Smuzhiyun	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
110*4882a593Smuzhiyun	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
111*4882a593Smuzhiyun	bsrl		b1238_fix
112*4882a593Smuzhiyun	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
113*4882a593Smuzhiyun	orl		#sx_mask,E_BYTE(%a6)
114*4882a593Smuzhiyunno_e3_2:
115*4882a593Smuzhiyun	moveb		#INEX_VEC,EXC_VEC+1(%a6)
116*4882a593Smuzhiyun	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
117*4882a593Smuzhiyun	fmovemx	USER_FP0(%a6),%fp0-%fp3
118*4882a593Smuzhiyun	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
119*4882a593Smuzhiyun	frestore	(%a7)+
120*4882a593Smuzhiyun	unlk		%a6
121*4882a593Smuzhiyun	bral		real_inex
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunovfl_exit:
124*4882a593Smuzhiyun	bclrb	#E3,E_BYTE(%a6)	|test and clear E3 bit
125*4882a593Smuzhiyun	beqs	e1_set
126*4882a593Smuzhiyun|
127*4882a593Smuzhiyun| Clear dirty bit on dest resister in the frame before branching
128*4882a593Smuzhiyun| to b1238_fix.
129*4882a593Smuzhiyun|
130*4882a593Smuzhiyun	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
131*4882a593Smuzhiyun	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
132*4882a593Smuzhiyun	bsrl		b1238_fix		|test for bug1238 case
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
135*4882a593Smuzhiyun	orl		#sx_mask,E_BYTE(%a6)
136*4882a593Smuzhiyun	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
137*4882a593Smuzhiyun	fmovemx	USER_FP0(%a6),%fp0-%fp3
138*4882a593Smuzhiyun	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
139*4882a593Smuzhiyun	frestore	(%a7)+
140*4882a593Smuzhiyun	unlk		%a6
141*4882a593Smuzhiyun	bral		fpsp_done
142*4882a593Smuzhiyune1_set:
143*4882a593Smuzhiyun	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
144*4882a593Smuzhiyun	fmovemx	USER_FP0(%a6),%fp0-%fp3
145*4882a593Smuzhiyun	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
146*4882a593Smuzhiyun	unlk		%a6
147*4882a593Smuzhiyun	bral		fpsp_done
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun|
150*4882a593Smuzhiyun|	ovf_adj
151*4882a593Smuzhiyun|
152*4882a593Smuzhiyunovf_adj:
153*4882a593Smuzhiyun|
154*4882a593Smuzhiyun| Have a0 point to the correct operand.
155*4882a593Smuzhiyun|
156*4882a593Smuzhiyun	btstb	#E3,E_BYTE(%a6)	|test E3 bit
157*4882a593Smuzhiyun	beqs	ovf_e1
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun	lea	WBTEMP(%a6),%a0
160*4882a593Smuzhiyun	bras	ovf_com
161*4882a593Smuzhiyunovf_e1:
162*4882a593Smuzhiyun	lea	ETEMP(%a6),%a0
163*4882a593Smuzhiyun
164*4882a593Smuzhiyunovf_com:
165*4882a593Smuzhiyun	bclrb	#sign_bit,LOCAL_EX(%a0)
166*4882a593Smuzhiyun	sne	LOCAL_SGN(%a0)
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun	bsrl	g_opcls		|returns opclass in d0
169*4882a593Smuzhiyun	cmpiw	#3,%d0		|check for opclass3
170*4882a593Smuzhiyun	bnes	not_opc011
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun|
173*4882a593Smuzhiyun| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
174*4882a593Smuzhiyun| CCs are defined to be 'not affected' for the opclass3 instruction.
175*4882a593Smuzhiyun|
176*4882a593Smuzhiyun	moveb	FPSR_CC(%a6),L_SCR1(%a6)
177*4882a593Smuzhiyun	bsrl	ovf_r_x3	|returns a0 pointing to result
178*4882a593Smuzhiyun	moveb	L_SCR1(%a6),FPSR_CC(%a6)
179*4882a593Smuzhiyun	bral	store		|stores to memory or register
180*4882a593Smuzhiyun
181*4882a593Smuzhiyunnot_opc011:
182*4882a593Smuzhiyun	bsrl	ovf_r_x2	|returns a0 pointing to result
183*4882a593Smuzhiyun	bral	store		|stores to memory or register
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun	|end
186