xref: /netbsd/sys/arch/m68k/fpsp/x_unfl.sa (revision bf9ec67e)
1*	$NetBSD: x_unfl.sa,v 1.4 2001/09/16 16:34:32 wiz Exp $
2
3*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4*	M68000 Hi-Performance Microprocessor Division
5*	M68040 Software Package
6*
7*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8*	All rights reserved.
9*
10*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11*	To the maximum extent permitted by applicable law,
12*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14*	PARTICULAR PURPOSE and any warranty against infringement with
15*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16*	and any accompanying written materials.
17*
18*	To the maximum extent permitted by applicable law,
19*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
24*	and support of the SOFTWARE.
25*
26*	You are hereby granted a copyright license to use, modify, and
27*	distribute the SOFTWARE so long as this entire notice is retained
28*	without alteration in any modified and/or redistributed versions,
29*	and that such modified versions are clearly identified as such.
30*	No licenses are granted by implication, estoppel or otherwise
31*	under any patents or trademarks of Motorola, Inc.
32
33*
34*	x_unfl.sa 3.4 7/1/91
35*
36*	fpsp_unfl --- FPSP handler for underflow exception
37*
38* Trap disabled results
39*	For 881/2 compatibility, sw must denormalize the intermediate
40* result, then store the result.  Denormalization is accomplished
41* by taking the intermediate result (which is always normalized) and
42* shifting the mantissa right while incrementing the exponent until
43* it is equal to the denormalized exponent for the destination
44* format.  After denormalizatoin, the result is rounded to the
45* destination format.
46*
47* Trap enabled results
48* 	All trap disabled code applies.	In addition the exceptional
49* operand needs to made available to the user with a bias of $6000
50* added to the exponent.
51*
52
53X_UNFL	IDNT    2,1 Motorola 040 Floating Point Software Package
54
55	section	8
56
57	include	fpsp.h
58
59	xref	denorm
60	xref	round
61	xref	store
62	xref	g_rndpr
63	xref	g_opcls
64	xref	g_dfmtou
65	xref	real_unfl
66	xref	real_inex
67	xref	fpsp_done
68	xref	b1238_fix
69
70	xdef	fpsp_unfl
71fpsp_unfl:
72	link		a6,#-LOCAL_SIZE
73	fsave		-(a7)
74	movem.l		d0-d1/a0-a1,USER_DA(a6)
75	fmovem.x	fp0-fp3,USER_FP0(a6)
76	fmovem.l	fpcr/fpsr/fpiar,USER_FPCR(a6)
77
78*
79	bsr.l		unf_res	;denormalize, round & store interm op
80*
81* If underflow exceptions are not enabled, check for inexact
82* exception
83*
84	btst.b		#unfl_bit,FPCR_ENABLE(a6)
85	beq.b		ck_inex
86
87	btst.b		#E3,E_BYTE(a6)
88	beq.b		no_e3_1
89*
90* Clear dirty bit on dest resister in the frame before branching
91* to b1238_fix.
92*
93	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
94	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
95	bsr.l		b1238_fix		;test for bug1238 case
96	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
97	or.l		#sx_mask,E_BYTE(a6)
98no_e3_1:
99	movem.l		USER_DA(a6),d0-d1/a0-a1
100	fmovem.x	USER_FP0(a6),fp0-fp3
101	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
102	frestore	(a7)+
103	unlk		a6
104	bra.l		real_unfl
105*
106* It is possible to have either inex2 or inex1 exceptions with the
107* unfl.  If the inex enable bit is set in the FPCR, and either
108* inex2 or inex1 occurred, we must clean up and branch to the
109* real inex handler.
110*
111ck_inex:
112	move.b		FPCR_ENABLE(a6),d0
113	and.b		FPSR_EXCEPT(a6),d0
114	andi.b		#$3,d0
115	beq.b		unfl_done
116
117*
118* Inexact enabled and reported, and we must take an inexact exception
119*
120take_inex:
121	btst.b		#E3,E_BYTE(a6)
122	beq.b		no_e3_2
123*
124* Clear dirty bit on dest resister in the frame before branching
125* to b1238_fix.
126*
127	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
128	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
129	bsr.l		b1238_fix		;test for bug1238 case
130	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
131	or.l		#sx_mask,E_BYTE(a6)
132no_e3_2:
133	move.b		#INEX_VEC,EXC_VEC+1(a6)
134	movem.l         USER_DA(a6),d0-d1/a0-a1
135	fmovem.x        USER_FP0(a6),fp0-fp3
136	fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
137	frestore        (a7)+
138	unlk            a6
139	bra.l		real_inex
140
141unfl_done:
142	bclr.b		#E3,E_BYTE(a6)
143	beq.b		e1_set		;if set then branch
144*
145* Clear dirty bit on dest resister in the frame before branching
146* to b1238_fix.
147*
148	bfextu		CMDREG3B(a6){6:3},d0		;get dest reg no
149	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
150	bsr.l		b1238_fix		;test for bug1238 case
151	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
152	or.l		#sx_mask,E_BYTE(a6)
153	movem.l		USER_DA(a6),d0-d1/a0-a1
154	fmovem.x	USER_FP0(a6),fp0-fp3
155	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
156	frestore	(a7)+
157	unlk		a6
158	bra.l		fpsp_done
159e1_set:
160	movem.l		USER_DA(a6),d0-d1/a0-a1
161	fmovem.x	USER_FP0(a6),fp0-fp3
162	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
163	unlk		a6
164	bra.l		fpsp_done
165*
166*	unf_res --- underflow result calculation
167*
168unf_res:
169	bsr.l		g_rndpr		;returns RND_PREC in d0 0=ext,
170*					;1=sgl, 2=dbl
171*					;we need the RND_PREC in the
172*					;upper word for round
173	clr.w		-(a7)
174	move.w		d0,-(a7)	;copy RND_PREC to stack
175*
176*
177* If the exception bit set is E3, the exceptional operand from the
178* fpu is in WBTEMP; else it is in FPTEMP.
179*
180	btst.b		#E3,E_BYTE(a6)
181	beq.b		unf_E1
182unf_E3:
183	lea		WBTEMP(a6),a0	;a0 now points to operand
184*
185* Test for fsgldiv and fsglmul.  If the inst was one of these, then
186* force the precision to extended for the denorm routine.  Use
187* the user's precision for the round routine.
188*
189	move.w		CMDREG3B(a6),d1	;check for fsgldiv or fsglmul
190	andi.w		#$7f,d1
191	cmpi.w		#$30,d1		;check for sgldiv
192	beq.b		unf_sgl
193	cmpi.w		#$33,d1		;check for sglmul
194	bne.b		unf_cont	;if not, use fpcr prec in round
195unf_sgl:
196	clr.l		d0
197	move.w		#$1,(a7)	;override g_rndpr precision
198*					;force single
199	bra.b		unf_cont
200unf_E1:
201	lea		FPTEMP(a6),a0	;a0 now points to operand
202unf_cont:
203	bclr.b		#sign_bit,LOCAL_EX(a0)	;clear sign bit
204	sne		LOCAL_SGN(a0)		;store sign
205
206	bsr.l		denorm		;returns denorm, a0 points to it
207*
208* WARNING:
209*				;d0 has guard,round sticky bit
210*				;make sure that it is not corrupted
211*				;before it reaches the round subroutine
212*				;also ensure that a0 isn't corrupted
213
214*
215* Set up d1 for round subroutine d1 contains the PREC/MODE
216* information respectively on upper/lower register halves.
217*
218	bfextu		FPCR_MODE(a6){2:2},d1	;get mode from FPCR
219*						;mode in lower d1
220	add.l		(a7)+,d1		;merge PREC/MODE
221*
222* WARNING: a0 and d0 are assumed to be intact between the denorm and
223* round subroutines. All code between these two subroutines
224* must not corrupt a0 and d0.
225*
226*
227* Perform Round
228*	Input:		a0 points to input operand
229*			d0{31:29} has guard, round, sticky
230*			d1{01:00} has rounding mode
231*			d1{17:16} has rounding precision
232*	Output:		a0 points to rounded operand
233*
234
235	bsr.l		round		;returns rounded denorm at (a0)
236*
237* Differentiate between store to memory vs. store to register
238*
239unf_store:
240	bsr.l		g_opcls		;returns opclass in d0{2:0}
241	cmpi.b		#$3,d0
242	bne.b		not_opc011
243*
244* At this point, a store to memory is pending
245*
246opc011:
247	bsr.l		g_dfmtou
248	tst.b		d0
249	beq.b		ext_opc011	;If extended, do not subtract
250* 				;If destination format is sgl/dbl,
251	tst.b		LOCAL_HI(a0)	;If rounded result is normal,don't
252*					;subtract
253	bmi.b		ext_opc011
254	subq.w		#1,LOCAL_EX(a0)	;account for denorm bias vs.
255*				;normalized bias
256*				;          normalized   denormalized
257*				;single       $7f           $7e
258*				;double       $3ff          $3fe
259*
260ext_opc011:
261	bsr.l		store		;stores to memory
262	bra.b		unf_done	;finish up
263
264*
265* At this point, a store to a float register is pending
266*
267not_opc011:
268	bsr.l		store	;stores to float register
269*				;a0 is not corrupted on a store to a
270*				;float register.
271*
272* Set the condition codes according to result
273*
274	tst.l		LOCAL_HI(a0)	;check upper mantissa
275	bne.b		ck_sgn
276	tst.l		LOCAL_LO(a0)	;check lower mantissa
277	bne.b		ck_sgn
278	bset.b		#z_bit,FPSR_CC(a6) ;set condition codes if zero
279ck_sgn:
280	btst.b 		#sign_bit,LOCAL_EX(a0)	;check the sign bit
281	beq.b		unf_done
282	bset.b		#neg_bit,FPSR_CC(a6)
283
284*
285* Finish.
286*
287unf_done:
288	btst.b		#inex2_bit,FPSR_EXCEPT(a6)
289	beq.b		no_aunfl
290	bset.b		#aunfl_bit,FPSR_AEXCEPT(a6)
291no_aunfl:
292	rts
293
294	end
295