summaryrefslogtreecommitdiff
path: root/sys/arch/m68k/fpsp/x_unfl.sa
blob: 62d50982ced64c760f351996a1c9c28fc10d14de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
*	$OpenBSD: x_unfl.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
*	$NetBSD: x_unfl.sa,v 1.3 1994/10/26 07:50:30 cgd Exp $

*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
*	M68000 Hi-Performance Microprocessor Division
*	M68040 Software Package 
*
*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
*	All rights reserved.
*
*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
*	To the maximum extent permitted by applicable law,
*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
*	PARTICULAR PURPOSE and any warranty against infringement with
*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
*	and any accompanying written materials. 
*
*	To the maximum extent permitted by applicable law,
*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
*	and support of the SOFTWARE.  
*
*	You are hereby granted a copyright license to use, modify, and
*	distribute the SOFTWARE so long as this entire notice is retained
*	without alteration in any modified and/or redistributed versions,
*	and that such modified versions are clearly identified as such.
*	No licenses are granted by implication, estoppel or otherwise
*	under any patents or trademarks of Motorola, Inc.

*
*	x_unfl.sa 3.4 7/1/91
*
*	fpsp_unfl --- FPSP handler for underflow exception
*
* Trap disabled results
*	For 881/2 compatibility, sw must denormalize the intermediate 
* result, then store the result.  Denormalization is accomplished 
* by taking the intermediate result (which is always normalized) and 
* shifting the mantissa right while incrementing the exponent until 
* it is equal to the denormalized exponent for the destination 
* format.  After denormalizatoin, the result is rounded to the 
* destination format.
*		
* Trap enabled results
* 	All trap disabled code applies.	In addition the exceptional 
* operand needs to made available to the user with a bias of $6000 
* added to the exponent.
*

X_UNFL	IDNT    2,1 Motorola 040 Floating Point Software Package

	section	8

	include	fpsp.h

	xref	denorm
	xref	round
	xref	store
	xref	g_rndpr
	xref	g_opcls
	xref	g_dfmtou
	xref	real_unfl
	xref	real_inex
	xref	fpsp_done
	xref	b1238_fix

	xdef	fpsp_unfl
fpsp_unfl:
	link		a6,#-LOCAL_SIZE
	fsave		-(a7)
	movem.l		d0-d1/a0-a1,USER_DA(a6)
	fmovem.x	fp0-fp3,USER_FP0(a6)
	fmovem.l	fpcr/fpsr/fpiar,USER_FPCR(a6)

*
	bsr.l		unf_res	;denormalize, round & store interm op
*
* If underflow exceptions are not enabled, check for inexact
* exception
*
	btst.b		#unfl_bit,FPCR_ENABLE(a6)
	beq.b		ck_inex

	btst.b		#E3,E_BYTE(a6)
	beq.b		no_e3_1
*
* Clear dirty bit on dest resister in the frame before branching
* to b1238_fix.
*
	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
	bsr.l		b1238_fix		;test for bug1238 case
	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
	or.l		#sx_mask,E_BYTE(a6)
no_e3_1:
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore	(a7)+
	unlk		a6
	bra.l		real_unfl
*
* It is possible to have either inex2 or inex1 exceptions with the
* unfl.  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
	beq.b		unfl_done

*
* Inexact enabled and reported, and we must take an inexact exception
*	
take_inex:
	btst.b		#E3,E_BYTE(a6)
	beq.b		no_e3_2
*
* Clear dirty bit on dest resister in the frame before branching
* to b1238_fix.
*
	bfextu		CMDREG3B(a6){6:3},d0	;get dest reg no
	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
	bsr.l		b1238_fix		;test for bug1238 case
	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
	or.l		#sx_mask,E_BYTE(a6)
no_e3_2:
	move.b		#INEX_VEC,EXC_VEC+1(a6)
	movem.l         USER_DA(a6),d0-d1/a0-a1
	fmovem.x        USER_FP0(a6),fp0-fp3
	fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore        (a7)+
	unlk            a6
	bra.l		real_inex

unfl_done:
	bclr.b		#E3,E_BYTE(a6)
	beq.b		e1_set		;if set then branch
*
* Clear dirty bit on dest resister in the frame before branching
* to b1238_fix.
*
	bfextu		CMDREG3B(a6){6:3},d0		;get dest reg no
	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
	bsr.l		b1238_fix		;test for bug1238 case
	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
	or.l		#sx_mask,E_BYTE(a6)
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore	(a7)+
	unlk		a6
	bra.l		fpsp_done
e1_set:
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	unlk		a6
	bra.l		fpsp_done
*
*	unf_res --- underflow result calculation
*
unf_res:
	bsr.l		g_rndpr		;returns RND_PREC in d0 0=ext,
*					;1=sgl, 2=dbl
*					;we need the RND_PREC in the
*					;upper word for round
	clr.w		-(a7)	
	move.w		d0,-(a7)	;copy RND_PREC to stack
*
*
* If the exception bit set is E3, the exceptional operand from the
* fpu is in WBTEMP; else it is in FPTEMP.
*
	btst.b		#E3,E_BYTE(a6)
	beq.b		unf_E1
unf_E3:
	lea		WBTEMP(a6),a0	;a0 now points to operand
*
* Test for fsgldiv and fsglmul.  If the inst was one of these, then
* force the precision to extended for the denorm routine.  Use
* the user's precision for the round routine.
*
	move.w		CMDREG3B(a6),d1	;check for fsgldiv or fsglmul
	andi.w		#$7f,d1
	cmpi.w		#$30,d1		;check for sgldiv
	beq.b		unf_sgl
	cmpi.w		#$33,d1		;check for sglmul
	bne.b		unf_cont	;if not, use fpcr prec in round
unf_sgl:
	clr.l		d0
	move.w		#$1,(a7)	;override g_rndpr precision
*					;force single
	bra.b		unf_cont
unf_E1:
	lea		FPTEMP(a6),a0	;a0 now points to operand
unf_cont:
	bclr.b		#sign_bit,LOCAL_EX(a0)	;clear sign bit
	sne		LOCAL_SGN(a0)		;store sign

	bsr.l		denorm		;returns denorm, a0 points to it
*
* WARNING:
*				;d0 has guard,round sticky bit
*				;make sure that it is not corrupted
*				;before it reaches the round subroutine
*				;also ensure that a0 isn't corrupted

*
* Set up d1 for round subroutine d1 contains the PREC/MODE
* information respectively on upper/lower register halves.
*
	bfextu		FPCR_MODE(a6){2:2},d1	;get mode from FPCR
*						;mode in lower d1
	add.l		(a7)+,d1		;merge PREC/MODE
*
* WARNING: a0 and d0 are assumed to be intact between the denorm and
* round subroutines. All code between these two subroutines
* must not corrupt a0 and d0.
*
*
* Perform Round	
*	Input:		a0 points to input operand
*			d0{31:29} has guard, round, sticky
*			d1{01:00} has rounding mode
*			d1{17:16} has rounding precision
*	Output:		a0 points to rounded operand
*

	bsr.l		round		;returns rounded denorm at (a0)
*
* Differentiate between store to memory vs. store to register
*
unf_store:
	bsr.l		g_opcls		;returns opclass in d0{2:0}
	cmpi.b		#$3,d0
	bne.b		not_opc011
*
* At this point, a store to memory is pending
*
opc011:
	bsr.l		g_dfmtou
	tst.b		d0
	beq.b		ext_opc011	;If extended, do not subtract
* 				;If destination format is sgl/dbl, 
	tst.b		LOCAL_HI(a0)	;If rounded result is normal,don't
*					;subtract
	bmi.b		ext_opc011
	subq.w		#1,LOCAL_EX(a0)	;account for denorm bias vs.
*				;normalized bias
*				;          normalized   denormalized
*				;single       $7f           $7e
*				;double       $3ff          $3fe
*
ext_opc011:
	bsr.l		store		;stores to memory
	bra.b		unf_done	;finish up

*
* At this point, a store to a float register is pending
*
not_opc011:
	bsr.l		store	;stores to float register
*				;a0 is not corrupted on a store to a
*				;float register.
*
* Set the condition codes according to result
*
	tst.l		LOCAL_HI(a0)	;check upper mantissa
	bne.b		ck_sgn
	tst.l		LOCAL_LO(a0)	;check lower mantissa
	bne.b		ck_sgn
	bset.b		#z_bit,FPSR_CC(a6) ;set condition codes if zero
ck_sgn:
	btst.b 		#sign_bit,LOCAL_EX(a0)	;check the sign bit
	beq.b		unf_done
	bset.b		#neg_bit,FPSR_CC(a6)

*
* Finish.  
*
unf_done:
	btst.b		#inex2_bit,FPSR_EXCEPT(a6)
	beq.b		no_aunfl
	bset.b		#aunfl_bit,FPSR_AEXCEPT(a6)
no_aunfl:
	rts

	end